diff --git a/Random.txt b/Random.txt index 9851d311a9..34c2b34b5c 100644 --- a/Random.txt +++ b/Random.txt @@ -1 +1 @@ -d66a871d990a1084502f4856b3d66c35 +462c8b20925f8d3f87f0ab82d25d9c2a diff --git a/Telegram/Telegram-iOS/Resources/Gift12.tgs b/Telegram/Telegram-iOS/Resources/Gift12.tgs new file mode 100644 index 0000000000..3fb5c07907 Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/Gift12.tgs differ diff --git a/Telegram/Telegram-iOS/Resources/Gift3.tgs b/Telegram/Telegram-iOS/Resources/Gift3.tgs new file mode 100644 index 0000000000..42bfb3cbcd Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/Gift3.tgs differ diff --git a/Telegram/Telegram-iOS/Resources/Gift6.tgs b/Telegram/Telegram-iOS/Resources/Gift6.tgs new file mode 100644 index 0000000000..be7a587354 Binary files /dev/null and b/Telegram/Telegram-iOS/Resources/Gift6.tgs differ diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 8e6fe46ea0..9aea810170 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -106,6 +106,8 @@ "PUSH_MESSAGE_FILES_TEXT_any" = "sent you %d files"; "PUSH_MESSAGE_THEME" = "%1$@|changed chat theme to %2$@"; "PUSH_MESSAGE_NOTHEME" = "%1$@|disabled chat theme"; +"PUSH_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@"; +"CHAT_MESSAGE_RECURRING_PAY" = "%1$@|You were charged %2$@"; "PUSH_CHANNEL_MESSAGE_TEXT" = "%1$@|%2$@"; "PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message"; @@ -7542,7 +7544,7 @@ Sorry for the inconvenience."; "Channel.AddUserKickedError" = "Sorry, you can't add this user because they are on the list of Removed Users and you can't unban them."; "Channel.AddAdminKickedError" = "Sorry, you can't add this user as an admin because they are in the Removed Users list and you can't unban them."; -"Premium.Stickers.Description" = "Unlock this sticker and more by subscribing to Telegram Premium."; +"Premium.Stickers.Description" = "Unlock this sticker and many more by subscribing to Telegram Premium."; "Premium.Stickers.Proceed" = "Unlock Premium Stickers"; "Premium.Reactions.Proceed" = "Unlock Premium Reactions"; @@ -7591,9 +7593,9 @@ Sorry for the inconvenience."; "Premium.MaxFileSizeNoPremiumText" = "The document can't be sent, because it is larger than **%@**. We are working to let you increase this limit in the future."; "Premium.MaxFileSizeFinalText" = "The document can't be sent, because it is larger than **%@**."; -"Premium.MaxPinsText" = "Sorry, you can't pin more than **%1$@** chats to the top. Unpin some of the currently pinned ones or subscribe to **Telegram Premium** to double the limit to **%2$@** chats."; -"Premium.MaxPinsNoPremiumText" = "Sorry, you can't pin more than **%@** chats to the top. Unpin some of the currently pinned ones."; -"Premium.MaxPinsFinalText" = "Sorry, you can't pin more than **%@** chats to the top. Unpin some of the currently pinned ones."; +"Premium.MaxPinsText" = "Sorry, you can't pin more than **%1$@** chats to the top. Unpin some that are currently pinned or subscribe to **Telegram Premium** to double the limit to **%2$@** chats."; +"Premium.MaxPinsNoPremiumText" = "Sorry, you can't pin more than **%@** chats to the top. Unpin some that are currently pinned."; +"Premium.MaxPinsFinalText" = "Sorry, you can't pin more than **%@** chats to the top. Unpin some that are currently pinned."; "Premium.MaxFavedStickersTitle" = "The Limit of %@ Stickers Reached"; "Premium.MaxFavedStickersText" = "An older sticker was replaced with this one. You can [increase the limit]() to %@ stickers."; @@ -7603,7 +7605,7 @@ Sorry for the inconvenience."; "Premium.MaxSavedGifsText" = "An older GIF was replaced with this one. You can [increase the limit]() to %@ GIFS."; "Premium.MaxSavedGifsFinalText" = "An older GIF was replaced with this one."; -"Premium.MaxAccountsText" = "You have reached the limit of **%@** connected accounts. You can free one place by subscribing to **Telegram Premium**."; +"Premium.MaxAccountsText" = "You have reached the limit of **%@** connected accounts. You can add more by subscribing to **Telegram Premium**."; "Premium.MaxAccountsNoPremiumText" = "You have reached the limit of **%@** connected accounts."; "Premium.MaxAccountsFinalText" = "You have reached the limit of **%@** connected accounts."; @@ -7634,10 +7636,10 @@ Sorry for the inconvenience."; "Premium.NoAds" = "No Ads"; "Premium.NoAdsInfo" = "No more ads in public channels where Telegram sometimes shows ads."; -"Premium.NoAdsStandaloneInfo" = "Remove ads such as this by subscribing to **Telegram Premium**."; +"Premium.NoAdsStandaloneInfo" = "Remove ads such as this one by subscribing to **Telegram Premium**."; "Premium.Reactions" = "Unique Reactions"; -"Premium.ReactionsInfo" = "Additional animated reactions on messages, available only to the Premium subscribers."; +"Premium.ReactionsInfo" = "Additional animated reactions on messages, available only to Premium subscribers."; "Premium.ReactionsStandalone" = "Additional Reactions"; "Premium.ReactionsStandaloneInfo" = "Unlock a wider range of reactions on messages by subscribing to **Telegram Premium**."; @@ -7646,7 +7648,7 @@ Sorry for the inconvenience."; "Premium.StickersInfo" = "Exclusive enlarged stickers featuring additional effects, updated monthly."; "Premium.ChatManagement" = "Advanced Chat Management"; -"Premium.ChatManagementInfo" = "Tools to set default folder, auto-archive and hide new chats."; +"Premium.ChatManagementInfo" = "Tools to set the default folder, auto-archive and hide new chats from non-contacts."; "Premium.Badge" = "Profile Badge"; "Premium.BadgeInfo" = "A badge next to your name showing that you are helping support Telegram."; @@ -7665,10 +7667,10 @@ Sorry for the inconvenience."; "Premium.AboutTitle" = "ABOUT TELEGRAM PREMIUM"; "Premium.AboutText" = "While the free version of Telegram already gives its users more than any other messaging application, **Telegram Premium** pushes its capabilities even further.\n\n**Telegram Premium** is a paid option, because most Premium Features require additional expenses from Telegram to third parties such as data center providers and server manufacturers. Contributions from **Telegram Premium** users allow us to cover such costs and also help Telegram stay free for everyone."; -"Premium.Terms" = "By purchasing a Premium subscription, you agree to our [Terms of Service](terms) and [Privacy Policy](privacy)."; +"Premium.Terms" = "By purchasing a Premium subscription, you agree to the Telegram [Terms of Service](terms) and [Privacy Policy](privacy)."; "Conversation.CopyProtectionSavingDisabledSecret" = "Saving is restricted"; -"Conversation.CopyProtectionForwardingDisabledSecret" = "Forwards are restricted"; +"Conversation.CopyProtectionForwardingDisabledSecret" = "Forwarding is restricted"; "Settings.Terms_URL" = "https://telegram.org/tos"; "Settings.PrivacyPolicy_URL" = "https://telegram.org/privacy"; @@ -7676,7 +7678,7 @@ Sorry for the inconvenience."; "Stickers.PremiumPackInfoText" = "This pack contains premium stickers like this one."; "Stickers.PremiumPackView" = "View"; -"Conversation.PremiumUploadFileTooLarge" = "File could not be sent, because it is larger than 4 GB.\n\nYou can send as many files as you like, but each must be smaller than 4 GB."; +"Conversation.PremiumUploadFileTooLarge" = "File could not be sent because it is larger than 4 GB.\n\nYou can send as many files as you like, but each must be smaller than 4 GB."; "SponsoredMessageMenu.Hide" = "Hide"; @@ -7707,7 +7709,7 @@ Sorry for the inconvenience."; "WebApp.Settings" = "Settings"; -"Bot.AccepRecurrentInfo" = "I accept [Terms of Service]() of **%1$@**"; +"Bot.AccepRecurrentInfo" = "I accept the [Terms of Service]() of **%1$@**"; "Chat.AudioTranscriptionRateAction" = "Rate Transcription"; "Chat.AudioTranscriptionFeedbackTip" = "Thank you for your feedback."; @@ -7798,4 +7800,138 @@ Sorry for the inconvenience."; "DeleteAccount.Success" = "The account has been successfully deleted."; +"PeerInfo.GiftPremium" = "Gift Premium"; + +"Premium.Gift.Title" = "Gift Telegram Premium"; +"Premium.Gift.Description" = "Let **%@** enjoy exclusive features of Telegram with **Telegram Premium**."; +"Premium.Gift.Info" = "You can review the list of features and terms of use for Telegram Premium [here]()."; +"Premium.Gift.GiftSubscription" = "Gift Subscription for %@"; + +"Premium.Gift.PricePerMonth" = "%@ / month"; + +"Premium.Gift.Months_1" = "%@ Month"; +"Premium.Gift.Months_any" = "%@ Months"; + +"Premium.Gift.Years_1" = "%@ Year"; +"Premium.Gift.Years_any" = "%@ Years"; + +"Premium.GiftedTitle" = "Telegram Premium"; + +"Premium.GiftedTitle.3Month" = "[%@]() has gifted you a 3-month subscription for Telegram Premium"; +"Premium.GiftedTitle.6Month" = "[%@]() has gifted you a 6-month subscription for Telegram Premium"; +"Premium.GiftedTitle.12Month" = "[%@]() has gifted you a 12-month subscription for Telegram Premium"; +"Premium.GiftedDescription" = "You now have access to additional features."; + +"Premium.GiftedTitleYou.3Month" = "You gifted [%@]() a 3-month subscription for Telegram Premium"; +"Premium.GiftedTitleYou.6Month" = "You gifted [%@]() a 6-month subscription for Telegram Premium"; +"Premium.GiftedTitleYou.12Month" = "You gifted [%@]() a 12-month subscription for Telegram Premium"; +"Premium.GiftedDescriptionYou" = "They now have access to additional features."; + "SettingsSearch.DeleteAccount.DeleteMyAccount" = " "; + +"Notification.PremiumGift.Sent" = "%1$@ sent you a gift for %2$@"; +"Notification.PremiumGift.SentYou" = "You sent a gift for %@"; + +"Notification.PremiumGift.Months_1" = "%@ month"; +"Notification.PremiumGift.Months_any" = "%@ months"; + +"Notification.PremiumGift.Title" = "Telegram Premium"; +"Notification.PremiumGift.Subtitle" = "for %@"; +"Notification.PremiumGift.View" = "View"; + +"StickerPack.AddEmojiCount_1" = "Add 1 Emoji"; +"StickerPack.AddEmojiCount_any" = "Add %@ Emoji"; + +"StickerPack.RemoveEmojiCount_1" = "Remove 1 Emoji"; +"StickerPack.RemoveEmojiCount_any" = "Remove %@ Emoji"; + +"StickerPack.AddEmojiPacksCount_1" = "Add 1 Emoji Pack"; +"StickerPack.AddEmojiPacksCount_any" = "Add %@ Emoji Packs"; + +"StickerPack.RemoveEmojiPacksCount_1" = "Remove 1 Emoji Packs"; +"StickerPack.RemoveEmojiPacksCount_any" = "Remove %@ Emoji Packs"; + +"Gallery.AirPlay" = "AirPlay"; +"Gallery.AirPlayPlaceholder" = "This video is playing on the TV using AirPlay"; + +"WebApp.CloseConfirmation" = "Changes that you made may not be saved."; +"WebApp.CloseAnyway" = "Close Anyway"; + +"Privacy.VoiceMessages" = "Voice Messages"; + +"Privacy.VoiceMessages.Tooltip" = "Only subscribers of [Telegram Premium]() can restrict receiving voice messages."; + +"Privacy.VoiceMessages.WhoCanSend" = "WHO CAN SEND ME VOICE MESSAGES"; +"Privacy.VoiceMessages.CustomHelp" = "You can restrict who can send you voice messages with granular precision."; +"Privacy.VoiceMessages.AlwaysAllow.Title" = "Always Allow"; +"Privacy.VoiceMessages.NeverAllow.Title" = "Never Allow"; +"Privacy.VoiceMessages.CustomShareHelp" = "These users will or will not be able to send you voice messages regardless of the settings above."; + +"Premium.AnimatedEmoji" = "Animated Emoji"; +"Premium.AnimatedEmojiInfo" = "Include animated emoji from different emoji sets in any message you send."; + +"ChatContextMenu.EmojiSetSingle" = "This message contains\n#[%@]() emoji."; +"ChatContextMenu.EmojiSet_1" = "This message contains emoji from [%@ pack]()."; +"ChatContextMenu.EmojiSet_any" = "This message contains emoji from [%@ packs]()."; + +"EmojiPack.Title" = "Emoji"; +"EmojiPack.Emoji_1" = "%@ emoji"; +"EmojiPack.Emoji_any" = "%@ emoji"; +"EmojiPack.Add" = "Add"; +"EmojiPack.Added" = "Added"; + +"EmojiPackActionInfo.AddedTitle" = "Emoji Added"; +"EmojiPackActionInfo.AddedText" = "%@ has been added to your emoji."; +"EmojiPackActionInfo.RemovedTitle" = "Emoji Removed"; +"EmojiPackActionInfo.ArchivedTitle" = "Emoji Archived"; +"EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji."; + +"EmojiPackActionInfo.MultipleAddedText_1" = "%@ pack has been added to your emoji."; +"EmojiPackActionInfo.MultipleAddedText_any" = "%@ packs have been added to your emoji."; + +"EmojiPackActionInfo.MultipleRemovedText_1" = "%@ pack is no longer in your emoji."; +"EmojiPackActionInfo.MultipleRemovedText_any" = "%@ packs are no longer in your emoji."; + +"MaskPackActionInfo.RemovedTitle" = "Masks Removed"; +"MaskPackActionInfo.ArchivedTitle" = "Masks Archived"; +"MaskPackActionInfo.RemovedText" = "%@ is no longer in your masks."; + +"WebApp.ShareMyPhoneNumber" = "Share My Phone Number"; +"WebApp.ShareMyPhoneNumberConfirmation" = "Are you sure you want to share your phone number **%1$@** with **%2$@**?"; + +"Conversation.VoiceMessagesRestricted" = "%@ doesn't accept voice and video messages"; + +"Emoji.ClearRecent" = "Clear Recent Emoji"; + +"Premium.AnimatedEmoji.Proceed" = "Unlock Animated Emoji"; + +"EmojiPacksSettings.Title" = "Emoji"; + +"EmojiStickerSettings.Info" = "Artists are welcome to add their own emoji sets using our @stickers bot.\n\nTap on a message to view and add the whole set."; + +"StickerPack.MaskCount_1" = "1 mask"; +"StickerPack.MaskCount_any" = "%@ masks"; + +"StickerPack.EmojiCount_1" = "1 emoji"; +"StickerPack.EmojiCount_any" = "%@ emoji"; + +"StickerSettings.EmojiContextInfo" = "If you archive an emoji set, you can quickly restore it later from the Archived Emoji section."; + +"StickerPack.CopyLinks" = "Copy Links"; +"Conversation.LinksCopied" = "Links copied to clipboard"; + +"StickersList.EmojiItem" = "Custom Emoji"; +"StickersList.ArchivedEmojiItem" = "Archived Emoji"; + +"EmojiInput.UnlockPack" = "Unlock %@"; +"EmojiInput.AddPack" = "Add %@"; +"EmojiInput.PanelTitlePremium" = "Premium"; +"EmojiInput.PanelTitleEmoji" = "Emoji"; +"EmojiInput.PanelTitleRecent" = "Recent"; + +"EmojiInput.SectionTitleEmoji" = "Emoji"; +"EmojiInput.SectionTitleFavoriteStickers" = "Favorite Stickers"; +"EmojiInput.SectionTitlePremiumStickers" = "Premium Stickers"; + +"EmojiInput.PremiumEmojiToast.Text" = "Subscribe to Telegram Premium to unlock premium emoji."; +"EmojiInput.PremiumEmojiToast.Action" = "More"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index a8cc36c4a2..758799c0e7 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -260,6 +260,11 @@ public struct ResolvedBotAdminRights: OptionSet { } } +public enum StickerPackUrlType { + case stickers + case emoji +} + public enum ResolvedUrl { case externalUrl(String) case urlAuth(String) @@ -269,7 +274,7 @@ public enum ResolvedUrl { case groupBotStart(peerId: PeerId, payload: String, adminRights: ResolvedBotAdminRights?) case channelMessage(peerId: PeerId, messageId: MessageId, timecode: Double?) case replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage, messageId: MessageId) - case stickerPack(name: String) + case stickerPack(name: String, type: StickerPackUrlType) case instantView(TelegramMediaWebpage, String?) case proxy(host: String, port: Int32, username: String?, password: String?, secret: Data?) case join(String) @@ -724,7 +729,7 @@ public protocol SharedAccountContext: AnyObject { func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set) -> Signal func chatAvailableMessageActions(engine: TelegramEngine, accountPeerId: EnginePeer.Id, messageIds: Set, messages: [EngineMessage.Id: EngineMessage], peers: [EnginePeer.Id: EnginePeer]) -> Signal func resolveUrl(context: AccountContext, peerId: PeerId?, url: String, skipUrlAuth: Bool) -> Signal - func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) + func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) func openAddContact(context: AccountContext, firstName: String, lastName: String, phoneNumber: String, label: String, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void) func openAddPersonContact(context: AccountContext, peerId: PeerId, pushController: @escaping (ViewController) -> Void, present: @escaping (ViewController, Any?) -> Void) func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) @@ -739,6 +744,8 @@ public protocol SharedAccountContext: AnyObject { func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController + func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController + func navigateToCurrentCall() var hasOngoingCall: ValuePromise { get } var immediateHasOngoingCall: Bool { get } diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 63a69e990c..764839370a 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -198,8 +198,8 @@ public struct ChatInterfaceForwardOptionsState: Codable, Equatable { } public struct ChatTextInputState: Codable, Equatable { - public let inputText: NSAttributedString - public let selectionRange: Range + public var inputText: NSAttributedString + public var selectionRange: Range public static func ==(lhs: ChatTextInputState, rhs: ChatTextInputState) -> Bool { return lhs.inputText.isEqual(to: rhs.inputText) && lhs.selectionRange == rhs.selectionRange @@ -249,6 +249,7 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { case monospace case textMention(EnginePeer.Id) case textUrl(String) + case customEmoji(stickerPack: StickerPackReference?, fileId: Int64) public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) @@ -266,6 +267,10 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { case 4: let url = (try? container.decode(String.self, forKey: "url")) ?? "" self = .textUrl(url) + case 5: + let stickerPack = try container.decodeIfPresent(StickerPackReference.self, forKey: "s") + let fileId = try container.decode(Int64.self, forKey: "f") + self = .customEmoji(stickerPack: stickerPack, fileId: fileId) default: assertionFailure() self = .bold @@ -287,6 +292,10 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { case let .textUrl(url): try container.encode(4 as Int32, forKey: "t") try container.encode(url, forKey: "url") + case let .customEmoji(stickerPack, fileId): + try container.encode(5 as Int32, forKey: "t") + try container.encodeIfPresent(stickerPack, forKey: "s") + try container.encode(fileId, forKey: "f") } } } @@ -352,6 +361,8 @@ public struct ChatTextInputStateText: Codable, Equatable { parsedAttributes.append(ChatTextInputStateTextAttribute(type: .textMention(value.peerId), range: range.location ..< (range.location + range.length))) } else if key == ChatTextInputAttributes.textUrl, let value = value as? ChatTextInputTextUrlAttribute { parsedAttributes.append(ChatTextInputStateTextAttribute(type: .textUrl(value.url), range: range.location ..< (range.location + range.length))) + } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { + parsedAttributes.append(ChatTextInputStateTextAttribute(type: .customEmoji(stickerPack: value.stickerPack, fileId: value.fileId), range: range.location ..< (range.location + range.length))) } } }) @@ -388,6 +399,8 @@ public struct ChatTextInputStateText: Codable, Equatable { result.addAttribute(ChatTextInputAttributes.textMention, value: ChatTextInputTextMentionAttribute(peerId: id), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) case let .textUrl(url): result.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: url), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) + case let .customEmoji(stickerPack, fileId): + result.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) } } return result @@ -456,7 +469,7 @@ public enum ChatPresentationInputQueryResult: Equatable { case hashtags([String]) case mentions([EnginePeer]) case commands([PeerCommand]) - case emojis([(String, String)], NSRange) + case emojis([(String, TelegramMediaFile?, String)], NSRange) case contextRequestResult(EnginePeer?, ChatContextResultCollection?) public static func ==(lhs: ChatPresentationInputQueryResult, rhs: ChatPresentationInputQueryResult) -> Bool { @@ -500,7 +513,13 @@ public enum ChatPresentationInputQueryResult: Equatable { return false } for i in 0 ..< lhsValue.count { - if lhsValue[i] != rhsValue[i] { + if lhsValue[i].0 != rhsValue[i].0 { + return false + } + if lhsValue[i].1?.fileId != rhsValue[i].1?.fileId { + return false + } + if lhsValue[i].2 != rhsValue[i].2 { return false } } @@ -541,6 +560,8 @@ public protocol ChatController: ViewController { func beginMessageSearch(_ query: String) func displayPromoAnnouncement(text: String) + func hintPlayNextOutgoingGift() + var isSendButtonVisible: Bool { get } } diff --git a/submodules/AccountContext/Sources/OpenChatMessage.swift b/submodules/AccountContext/Sources/OpenChatMessage.swift index 57da66c17d..b5eb81cad0 100644 --- a/submodules/AccountContext/Sources/OpenChatMessage.swift +++ b/submodules/AccountContext/Sources/OpenChatMessage.swift @@ -36,7 +36,7 @@ public final class OpenChatMessageParams { public let openPeer: (Peer, ChatControllerInteractionNavigateToPeer) -> Void public let callPeer: (PeerId, Bool) -> Void public let enqueueMessage: (EnqueueMessage) -> Void - public let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + public let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? public let setupTemporaryHiddenMedia: (Signal, Int, Media) -> Void public let chatAvatarHiddenMedia: (Signal, Media) -> Void public let actionInteraction: GalleryControllerActionInteraction? @@ -63,7 +63,7 @@ public final class OpenChatMessageParams { openPeer: @escaping (Peer, ChatControllerInteractionNavigateToPeer) -> Void, callPeer: @escaping (PeerId, Bool) -> Void, enqueueMessage: @escaping (EnqueueMessage) -> Void, - sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, + sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, setupTemporaryHiddenMedia: @escaping (Signal, Int, Media) -> Void, chatAvatarHiddenMedia: @escaping (Signal, Media) -> Void, actionInteraction: GalleryControllerActionInteraction? = nil, diff --git a/submodules/AlertUI/Sources/ThemedTextAlertController.swift b/submodules/AlertUI/Sources/ThemedTextAlertController.swift index 99c962e8f9..fcc13819ae 100644 --- a/submodules/AlertUI/Sources/ThemedTextAlertController.swift +++ b/submodules/AlertUI/Sources/ThemedTextAlertController.swift @@ -18,7 +18,7 @@ public func textAlertController(alertContext: AlertControllerContext, title: Str let presentationDataDisposable = alertContext.themeSignal.start(next: { [weak controller] theme in controller?.theme = theme }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } @@ -44,7 +44,7 @@ public func richTextAlertController(alertContext: AlertControllerContext, title: let presentationDataDisposable = alertContext.themeSignal.start(next: { [weak controller] theme in controller?.theme = theme }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } diff --git a/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift b/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift index 99f320ca60..da854711f0 100644 --- a/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift +++ b/submodules/AnimatedStickerNode/Sources/AnimatedStickerNode.swift @@ -165,6 +165,7 @@ public protocol AnimatedStickerNode: ASDisplayNode { var autoplay: Bool { get set } var visibility: Bool { get set } + var overrideVisibility: Bool { get set } var isPlayingChanged: (Bool) -> Void { get } @@ -222,6 +223,7 @@ public final class DefaultAnimatedStickerNodeImpl: ASDisplayNode, AnimatedSticke } public var autoplay = false + public var overrideVisibility: Bool = false public var visibility = false { didSet { @@ -386,7 +388,7 @@ public final class DefaultAnimatedStickerNodeImpl: ASDisplayNode, AnimatedSticke private func updateIsPlaying() { if !self.autoplay { - let isPlaying = self.visibility && self.isDisplaying + let isPlaying = self.visibility && (self.isDisplaying || self.overrideVisibility) if self.isPlaying != isPlaying { self.isPlaying = isPlaying if isPlaying { diff --git a/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift b/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift index 76ed877028..9a36f9148d 100644 --- a/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift +++ b/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift @@ -56,6 +56,8 @@ public final class DirectAnimatedStickerNode: ASDisplayNode, AnimatedStickerNode } } + public var overrideVisibility: Bool = false + public var isPlayingChanged: (Bool) -> Void = { _ in } private var sourceDisposable: Disposable? diff --git a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift index 166f7cdf80..93eb8c659b 100644 --- a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift +++ b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift @@ -272,6 +272,10 @@ private final class VideoStickerFrameSourceCache { private let useCache = true +public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool) -> AnimatedStickerFrameSource? { + return VideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: cachePathPrefix, unpremultiplyAlpha: unpremultiplyAlpha) +} + final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { private let queue: Queue private let path: String @@ -289,7 +293,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { return self.currentFrame % self.frameCount } - init?(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?) { + init?(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool = true) { self.queue = queue self.path = path self.width = width @@ -306,7 +310,7 @@ final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { self.frameRate = Int(cache.frameRate) self.frameCount = Int(cache.frameCount) } else { - let source = SoftwareVideoSource(path: path, hintVP9: true) + let source = SoftwareVideoSource(path: path, hintVP9: true, unpremultiplyAlpha: unpremultiplyAlpha) self.source = source self.frameRate = min(30, source.getFramerate()) self.frameCount = 0 diff --git a/submodules/AppLock/Sources/AppLock.swift b/submodules/AppLock/Sources/AppLock.swift index 2f8d668b27..49ec60fb5d 100644 --- a/submodules/AppLock/Sources/AppLock.swift +++ b/submodules/AppLock/Sources/AppLock.swift @@ -44,19 +44,23 @@ private func getCoveringViewSnaphot(window: Window1) -> UIImage? { context.clear(CGRect(origin: CGPoint(), size: size)) context.scaleBy(x: scale, y: scale) UIGraphicsPushContext(context) + + window.badgeView.alpha = 0.0 window.forEachViewController({ controller in if let controller = controller as? PasscodeEntryController { controller.displayNode.alpha = 0.0 } return true }) - window.hostView.containerView.drawHierarchy(in: CGRect(origin: CGPoint(), size: unscaledSize), afterScreenUpdates: false) + window.hostView.containerView.drawHierarchy(in: CGRect(origin: CGPoint(), size: unscaledSize), afterScreenUpdates: true) window.forEachViewController({ controller in if let controller = controller as? PasscodeEntryController { controller.displayNode.alpha = 1.0 } return true }) + window.badgeView.alpha = 1.0 + UIGraphicsPopContext() }).flatMap(applyScreenshotEffectToImage) } diff --git a/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift b/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift index 4a272a62ee..8e81d93b98 100644 --- a/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift +++ b/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift @@ -127,7 +127,15 @@ private final class ArchivedStickersNoticeAlertContentNode: AlertContentNode { var index: Int = 0 var entries: [ArchivedStickersNoticeEntry] = [] for pack in archivedStickerPacks { - entries.append(ArchivedStickersNoticeEntry(index: index, info: pack.0, topItem: pack.1, count: presentationData.strings.StickerPack_StickerCount(pack.0.count))) + let countTitle: String + if pack.0.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(pack.0.count) + } else if pack.0.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(pack.0.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(pack.0.count) + } + entries.append(ArchivedStickersNoticeEntry(index: index, info: pack.0, topItem: pack.1, count: countTitle)) index += 1 } @@ -304,7 +312,7 @@ public func archivedStickerPacksNoticeController(context: AccountContext, archiv let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller] presentationData in controller?.theme = AlertControllerTheme(presentationData: presentationData) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() disposable.dispose() } diff --git a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm index c73adc2330..bba12025a8 100644 --- a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm +++ b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm @@ -19,14 +19,14 @@ - (CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(nullable CGRect *)remainingRect { CGRect result = [super lineFragmentRectForProposedRect:proposedRect atIndex:characterIndex writingDirection:baseWritingDirection remainingRect:remainingRect]; -#if DEBUG +/*#if DEBUG if (result.origin.y < 10.0f) { result.size.width -= 21.0f; if (result.size.width < 0.0f) { result.size.width = 0.0f; } } -#endif +#endif*/ return result; } @@ -39,16 +39,17 @@ @implementation ASCustomLayoutManager -- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { - /*CGGlyph glyph = [self glyphAtIndex:glyphsToShow.location]; - if (glyph) { +- (void)showCGGlyphs:(const CGGlyph *)glyphs positions:(const CGPoint *)positions count:(NSUInteger)glyphCount font:(UIFont *)font matrix:(CGAffineTransform)textMatrix attributes:(NSDictionary *)attributes inContext:(CGContextRef)graphicsContext { + for (NSUInteger i = 0; i < glyphCount; i++) { + if (attributes[@"Attribute__CustomEmoji"] != nil) { + continue; + } + + [super showCGGlyphs:&glyphs[i] positions:&positions[i] count:1 font:font matrix:textMatrix attributes:attributes inContext:graphicsContext]; } - - CGRect bounds = [self boundingRectForGlyphRange:glyphsToShow inTextContainer:[self textContainerForGlyphAtIndex:glyphsToShow.location effectiveRange:nil]]; - CGContextRef context = UIGraphicsGetCurrentContext(); - CGContextSetFillColorWithColor(context, [UIColor grayColor].CGColor); - CGContextFillRect(context, bounds);*/ - +} + +- (void)drawGlyphsForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { [super drawGlyphsForGlyphRange:glyphsToShow atPoint:origin]; } @@ -171,8 +172,10 @@ // If our text-view's width is already the constrained width, we can use our existing TextKit stack for this sizing calculation. // Otherwise, we create a temporary stack to size for `constrainedWidth`. + UIEdgeInsets additionalInsets = UIEdgeInsetsZero; if (CGRectGetWidth(components.textView.threadSafeBounds) != constrainedWidth) { - components = [ASTextKitComponents componentsWithAttributedSeedString:components.textStorage textContainerSize:CGSizeMake(constrainedWidth, CGFLOAT_MAX)]; + additionalInsets = self.textView.textContainerInset; + components = [ASTextKitComponents componentsWithAttributedSeedString:components.textStorage textContainerSize:CGSizeMake(constrainedWidth - additionalInsets.left - additionalInsets.right, CGFLOAT_MAX)]; } // Force glyph generation and layout, which may not have happened yet (and isn't triggered by -usedRectForTextContainer:). diff --git a/submodules/AttachmentTextInputPanelNode/BUILD b/submodules/AttachmentTextInputPanelNode/BUILD index 0c9fa47d61..f82aeb9a52 100644 --- a/submodules/AttachmentTextInputPanelNode/BUILD +++ b/submodules/AttachmentTextInputPanelNode/BUILD @@ -29,6 +29,11 @@ swift_library( "//submodules/Pasteboard:Pasteboard", "//submodules/ContextUI:ContextUI", "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", + "//submodules/ComponentFlow:ComponentFlow", + "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities", ], visibility = [ "//visibility:public", diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 43a96c5d10..784a68f5c3 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -19,6 +19,11 @@ import TextInputMenu import ChatPresentationInterfaceState import Pasteboard import EmojiTextAttachmentView +import ComponentFlow +import LottieAnimationComponent +import AnimationCache +import MultiAnimationRenderer +import TextNodeWithEntities private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers]) private let minInputFontSize: CGFloat = 5.0 @@ -64,7 +69,7 @@ private func calculateTextFieldRealInsets(_ presentationInterfaceState: ChatPres top = 0.0 bottom = 0.0 } - return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: 0.0) + return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: 32.0) } private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, UIImage)? @@ -118,18 +123,91 @@ private class CaptionEditableTextNode: EditableTextNode { } } +public protocol AttachmentTextInputPanelInputView: UIView { + var insertText: ((NSAttributedString) -> Void)? { get set } + var deleteBackwards: (() -> Void)? { get set } + var switchToKeyboard: (() -> Void)? { get set } + var presentController: ((ViewController) -> Void)? { get set } +} + +final class CustomEmojiContainerView: UIView { + private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView? + + private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:] + + init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) { + self.emojiViewProvider = emojiViewProvider + + super.init(frame: CGRect()) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + func update(emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) { + var nextIndexById: [Int64: Int] = [:] + + var validKeys = Set() + for (rect, emoji) in emojiRects { + let index: Int + if let nextIndex = nextIndexById[emoji.fileId] { + index = nextIndex + } else { + index = 0 + } + nextIndexById[emoji.fileId] = index + 1 + + let key = InlineStickerItemLayer.Key(id: emoji.fileId, index: index) + + let view: UIView + if let current = self.emojiLayers[key] { + view = current + } else if let newView = self.emojiViewProvider(emoji) { + view = newView + self.addSubview(newView) + self.emojiLayers[key] = view + } else { + continue + } + + let size = CGSize(width: 24.0, height: 24.0) + + view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size) + + validKeys.insert(key) + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, view) in self.emojiLayers { + if !validKeys.contains(key) { + removeKeys.append(key) + view.removeFromSuperview() + } + } + for key in removeKeys { + self.emojiLayers.removeValue(forKey: key) + } + } +} + public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, ASEditableTextNodeDelegate { private let context: AccountContext private let isCaption: Bool private let isAttachment: Bool + private let presentController: (ViewController) -> Void + private let makeEntityInputView: () -> AttachmentTextInputPanelInputView? + private var textPlaceholderNode: ImmediateTextNode private let textInputContainerBackgroundNode: ASImageNode private let textInputContainer: ASDisplayNode public var textInputNode: EditableTextNode? private var dustNode: InvisibleInkDustNode? - private var oneLineNode: ImmediateTextNode + private var customEmojiContainerView: CustomEmojiContainerView? + private var oneLineNode: TextNodeWithEntities + private var oneLineNodeAttributedText: NSAttributedString? private var oneLineDustNode: InvisibleInkDustNode? let textInputBackgroundNode: ASDisplayNode @@ -137,6 +215,8 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS private var transparentTextInputBackgroundImage: UIImage? private let actionButtons: AttachmentTextInputActionButtonsNode private let counterTextNode: ImmediateTextNode + + private let inputModeView: ComponentHostView private var validLayout: (CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool)? @@ -242,15 +322,24 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS private var spoilersRevealed = false - private var emojiViewProvider: ((String) -> UIView)? + public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? + private let animationCache: AnimationCache + private let animationRenderer: MultiAnimationRenderer private var maxCaptionLength: Int32? - public init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, isCaption: Bool = false, isAttachment: Bool = false, presentController: @escaping (ViewController) -> Void) { + public init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, isCaption: Bool = false, isAttachment: Bool = false, presentController: @escaping (ViewController) -> Void, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) { self.context = context self.presentationInterfaceState = presentationInterfaceState self.isCaption = isCaption self.isAttachment = isAttachment + self.presentController = presentController + self.makeEntityInputView = makeEntityInputView + + self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + self.animationRenderer = MultiAnimationRendererImpl() var hasSpoilers = true if presentationInterfaceState.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat { @@ -266,6 +355,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS if !isCaption { self.textInputContainer.addSubnode(self.textInputContainerBackgroundNode) } + + self.inputModeView = ComponentHostView() + self.textInputContainer.view.addSubview(self.inputModeView) self.textInputContainer.clipsToBounds = true self.textInputBackgroundNode = ASDisplayNode() @@ -276,9 +368,8 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS self.textPlaceholderNode.maximumNumberOfLines = 1 self.textPlaceholderNode.isUserInteractionEnabled = false - self.oneLineNode = ImmediateTextNode() - self.oneLineNode.maximumNumberOfLines = 1 - self.oneLineNode.isUserInteractionEnabled = false + self.oneLineNode = TextNodeWithEntities() + self.oneLineNode.textNode.isUserInteractionEnabled = false self.actionButtons = AttachmentTextInputActionButtonsNode(presentationInterfaceState: presentationInterfaceState, presentController: presentController) self.counterTextNode = ImmediateTextNode() @@ -304,7 +395,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS self.addSubnode(self.counterTextNode) if isCaption { - self.addSubnode(self.oneLineNode) + self.addSubnode(self.oneLineNode.textNode) } self.textInputBackgroundImageNode.clipsToBounds = true @@ -314,15 +405,26 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS strongSelf.ensureFocused() } } + recognizer.waitForTouchUp = { [weak self] in + guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else { + return true + } + + if textInputNode.textView.isFirstResponder { + return true + } else { + return false + } + } self.textInputBackgroundNode.view.addGestureRecognizer(recognizer) - /*self.emojiViewProvider = { [weak self] emoji in - guard let strongSelf = self, let file = strongSelf.context.animatedEmojiStickers[emoji]?.first?.file else { + self.emojiViewProvider = { [weak self] emoji in + guard let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState else { return UIView() } - return EmojiTextAttachmentView(context: context, file: file) - }*/ + return EmojiTextAttachmentView(context: context, emoji: emoji, file: emoji.file, cache: strongSelf.animationCache, renderer: strongSelf.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12), pointSize: CGSize(width: 24.0, height: 24.0)) + } self.updateSendButtonEnabled(isCaption || isAttachment, animated: false) @@ -352,7 +454,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS guard let presentationInterfaceState = self.presentationInterfaceState else { return 0.0 } - return self.updateLayout(width: size.width, leftInset: sideInset, rightInset: sideInset, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: size.height, isSecondary: false, transition: .immediate, interfaceState: presentationInterfaceState, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact)) + return self.updateLayout(width: size.width, leftInset: sideInset, rightInset: sideInset, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: size.height, isSecondary: false, transition: .immediate, interfaceState: presentationInterfaceState, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), isMediaInputExpanded: false) } public func setCaption(_ caption: NSAttributedString?) { @@ -434,6 +536,17 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS strongSelf.ensureFocused() } } + recognizer.waitForTouchUp = { [weak self] in + guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else { + return true + } + + if textInputNode.textView.isFirstResponder { + return true + } else { + return false + } + } textInputNode.view.addGestureRecognizer(recognizer) textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string @@ -496,7 +609,15 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS return minimalHeight } - public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if !self.inputModeView.isHidden, let result = self.inputModeView.hitTest(self.view.convert(point, to: self.inputModeView), with: event) { + return result + } + + return super.hitTest(point, with: event) + } + + public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { let hadLayout = self.validLayout != nil let previousAdditionalSideInsets = self.validLayout?.3 self.validLayout = (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary) @@ -656,7 +777,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS if self.isCaption { if self.isFocused { - self.oneLineNode.alpha = 0.0 + self.oneLineNode.textNode.alpha = 0.0 self.oneLineDustNode?.alpha = 0.0 self.textInputNode?.alpha = 1.0 @@ -666,7 +787,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS } else { panelHeight = minimalHeight - transition.updateAlpha(node: self.oneLineNode, alpha: inputHasText ? 1.0 : 0.0) + transition.updateAlpha(node: self.oneLineNode.textNode, alpha: inputHasText ? 1.0 : 0.0) if let oneLineDustNode = self.oneLineDustNode { transition.updateAlpha(node: oneLineDustNode, alpha: inputHasText ? 1.0 : 0.0) } @@ -679,9 +800,34 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS transition.updateAlpha(node: self.textInputBackgroundImageNode, alpha: inputHasText ? 1.0 : 0.0) } - let oneLineSize = self.oneLineNode.updateLayout(CGSize(width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: CGFloat.greatestFiniteMagnitude)) - let oneLineFrame = CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: oneLineSize) - self.oneLineNode.frame = oneLineFrame + let makeOneLineLayout = TextNodeWithEntities.asyncLayout(self.oneLineNode) + let (oneLineLayout, oneLineApply) = makeOneLineLayout(TextNodeLayoutArguments( + attributedString: self.oneLineNodeAttributedText, + backgroundColor: nil, + minimumNumberOfLines: 1, + maximumNumberOfLines: 1, + truncationType: .end, + constrainedSize: CGSize(width: baseWidth - textFieldInsets.left - textFieldInsets.right, height: CGFloat.greatestFiniteMagnitude), + alignment: .left, + verticalAlignment: .top, + lineSpacing: 0.0, + cutout: nil, insets: UIEdgeInsets(), + lineColor: nil, + textShadowColor: nil, + textStroke: nil, + displaySpoilers: false, + displayEmbeddedItemsUnderSpoilers: false + )) + + let oneLineFrame = CGRect(origin: CGPoint(x: leftInset + textFieldInsets.left + self.textInputViewInternalInsets.left, y: textFieldInsets.top + self.textInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel), size: oneLineLayout.size) + self.oneLineNode.textNode.frame = oneLineFrame + let _ = oneLineApply(TextNodeWithEntities.Arguments( + context: self.context, + cache: self.animationCache, + renderer: self.animationRenderer, + placeholderColor: self.presentationInterfaceState?.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12) ?? .lightGray, + attemptSynchronous: false + )) self.updateOneLineSpoiler() } @@ -693,6 +839,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS if let textInputNode = self.textInputNode { let textFieldFrame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - textInputViewInternalInsets.bottom)) let shouldUpdateLayout = textFieldFrame.size != textInputNode.frame.size + if let presentationInterfaceState = self.presentationInterfaceState { + textInputNode.textContainerInset = calculateTextFieldRealInsets(presentationInterfaceState) + } transition.updateFrame(node: textInputNode, frame: textFieldFrame) if shouldUpdateLayout { textInputNode.layout() @@ -756,6 +905,34 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS var textInputViewRealInsets = UIEdgeInsets() if let presentationInterfaceState = self.presentationInterfaceState { textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState) + + var colors: [String: UIColor] = [:] + let colorKeys: [String] = [ + "__allcolors__" + ] + let color = defaultDarkPresentationTheme.chat.inputPanel.inputControlColor + for colorKey in colorKeys { + colors[colorKey] = color + } + let animationComponent = LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: self.textInputNode?.textView.inputView == nil ? "input_anim_smileToKey" : "input_anim_keyToSmile", + mode: .still(position: .begin) + ), + colors: colors, + size: CGSize(width: 32.0, height: 32.0) + ) + let inputNodeSize = self.inputModeView.update( + transition: .immediate, + component: AnyComponent(Button( + content: AnyComponent(animationComponent), + action: { [weak self] in + self?.toggleInputMode() + })), + environment: {}, + containerSize: CGSize(width: 32.0, height: 32.0) + ) + transition.updateFrame(view: self.inputModeView, frame: CGRect(origin: CGPoint(x: textInputBackgroundFrame.maxX - inputNodeSize.width - 1.0, y: textInputBackgroundFrame.maxY - inputNodeSize.height - 1.0), size: inputNodeSize)) } let placeholderFrame: CGRect @@ -804,6 +981,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS let textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor var rects: [CGRect] = [] + var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] if let attributedText = textInputNode.attributedText { let beginning = textInputNode.textView.beginningOfDocument @@ -841,6 +1019,16 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS addSpoiler(startIndex: currentStartIndex, endIndex: endIndex) } } + + if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + if let start = textInputNode.textView.position(from: beginning, offset: range.location), let end = textInputNode.textView.position(from: start, offset: range.length), let textRange = textInputNode.textView.textRange(from: start, to: end) { + let textRects = textInputNode.textView.selectionRects(for: textRange) + for textRect in textRects { + customEmojiRects.append((textRect.rect, value)) + break + } + } + } }) } @@ -861,6 +1049,28 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS dustNode.removeFromSupernode() self.dustNode = nil } + + if !customEmojiRects.isEmpty { + let customEmojiContainerView: CustomEmojiContainerView + if let current = self.customEmojiContainerView { + customEmojiContainerView = current + } else { + customEmojiContainerView = CustomEmojiContainerView(emojiViewProvider: { [weak self] emoji in + guard let strongSelf = self, let emojiViewProvider = strongSelf.emojiViewProvider else { + return nil + } + return emojiViewProvider(emoji) + }) + customEmojiContainerView.isUserInteractionEnabled = false + textInputNode.textView.addSubview(customEmojiContainerView) + self.customEmojiContainerView = customEmojiContainerView + } + + customEmojiContainerView.update(emojiRects: customEmojiRects) + } else if let customEmojiContainerView = self.customEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.customEmojiContainerView = nil + } } private func updateSpoilersRevealed(animated: Bool = true) { @@ -984,6 +1194,71 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS } } + private func toggleInputMode() { + self.loadTextInputNodeIfNeeded() + + guard let textInputNode = self.textInputNode else { + return + } + + var shouldHaveInputView = false + if textInputNode.textView.isFirstResponder { + if textInputNode.textView.inputView == nil { + shouldHaveInputView = true + } + } else { + shouldHaveInputView = true + } + + if shouldHaveInputView { + let inputView = self.makeEntityInputView() + inputView?.insertText = { [weak self] text in + guard let strongSelf = self else { + return + } + + strongSelf.interfaceInteraction?.updateTextInputStateAndMode { textInputState, inputMode in + let inputText = NSMutableAttributedString(attributedString: textInputState.inputText) + + let range = textInputState.selectionRange + inputText.replaceCharacters(in: NSMakeRange(range.lowerBound, range.count), with: text) + + let selectionPosition = range.lowerBound + (text.string as NSString).length + + return (ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition), inputMode) + } + } + inputView?.deleteBackwards = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.textInputNode?.textView.deleteBackward() + } + inputView?.switchToKeyboard = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.toggleInputMode() + } + inputView?.presentController = { [weak self] c in + guard let strongSelf = self else { + return + } + strongSelf.presentController(c) + } + + textInputNode.textView.inputView = inputView + } else { + textInputNode.textView.inputView = nil + } + + if textInputNode.textView.isFirstResponder { + textInputNode.textView.reloadInputViews() + } else { + textInputNode.textView.becomeFirstResponder() + } + } + private func updateTextNodeText(animated: Bool) { var inputHasText = false if let textInputNode = self.textInputNode, let attributedText = textInputNode.attributedText, attributedText.length != 0 { @@ -1005,12 +1280,12 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS let trimmedText = NSMutableAttributedString(attributedString: attributedText.attributedSubstring(from: NSMakeRange(0, range.location))) trimmedText.append(NSAttributedString(string: "\u{2026}", font: textFont, textColor: textColor)) - self.oneLineNode.attributedText = trimmedText + self.oneLineNodeAttributedText = trimmedText } else { - self.oneLineNode.attributedText = attributedText + self.oneLineNodeAttributedText = attributedText } } else { - self.oneLineNode.attributedText = nil + self.oneLineNodeAttributedText = nil } let panelHeight = self.updateTextHeight(animated: animated) @@ -1020,15 +1295,15 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS } private func updateOneLineSpoiler() { - if let textLayout = self.oneLineNode.cachedLayout, !textLayout.spoilers.isEmpty { + if let textLayout = self.oneLineNode.textNode.cachedLayout, !textLayout.spoilers.isEmpty { if self.oneLineDustNode == nil { let oneLineDustNode = InvisibleInkDustNode(textNode: nil) self.oneLineDustNode = oneLineDustNode - self.oneLineNode.supernode?.insertSubnode(oneLineDustNode, aboveSubnode: self.oneLineNode) + self.oneLineNode.textNode.supernode?.insertSubnode(oneLineDustNode, aboveSubnode: self.oneLineNode.textNode) } if let oneLineDustNode = self.oneLineDustNode { - let textFrame = self.oneLineNode.frame.insetBy(dx: 0.0, dy: -3.0) + let textFrame = self.oneLineNode.textNode.frame.insetBy(dx: 0.0, dy: -3.0) oneLineDustNode.update(size: textFrame.size, color: .white, textColor: .white, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 0.0, dy: 3.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 0.0, dy: 3.0) }) oneLineDustNode.frame = textFrame @@ -1110,7 +1385,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS self.focusUpdated?(true) if self.isCaption, let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary) = self.validLayout, let presentationInterfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: 0.0, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .animated(duration: 0.3, curve: .easeInOut), interfaceState: presentationInterfaceState, metrics: metrics) + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: 0.0, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .animated(duration: 0.3, curve: .easeInOut), interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: false) } } @@ -1121,7 +1396,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS self.focusUpdated?(false) if self.isCaption, let (width, leftInset, rightInset, additionalSideInsets, maxHeight, metrics, isSecondary) = self.validLayout, let presentationInterfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: 0.0, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .animated(duration: 0.3, curve: .easeInOut), interfaceState: presentationInterfaceState, metrics: metrics) + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: 0.0, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .animated(duration: 0.3, curve: .easeInOut), interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: false) } } diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index acb3bd1be9..bf75ed7100 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -37,6 +37,9 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { var interactivelyDismissed: (() -> Void)? var controllerRemoved: ((ViewController) -> Void)? + var shouldCancelPanGesture: (() -> Bool)? + var requestDismiss: (() -> Void)? + var updateModalProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var isUpdatingState = false @@ -232,6 +235,12 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { } } + if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { + self.cancelPanGesture() + self.requestDismiss?() + return + } + var bounds = self.bounds if self.isExpanded { bounds.origin.y = -max(0.0, translation - edgeTopInset) @@ -277,8 +286,13 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { let offset = currentTopInset + panOffset let topInset: CGFloat = edgeTopInset + var ignoreDismiss = false + if let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { + ignoreDismiss = true + } + var dismissing = false - if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0) { + if (bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) || (self.isExpanded && bounds.minY.isZero && velocity.y > 1800.0)) && !ignoreDismiss { self.interactivelyDismissed?() dismissing = true } else if self.isExpanded { @@ -340,6 +354,12 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { self.isAnimating = true self.update(layout: layout, controllers: controllers, coveredByModalTransition: coveredByModalTransition, transition: .animated(duration: 0.3, curve: .easeInOut), completion: completion) + + var bounds = self.bounds + let previousBounds = bounds + bounds.origin.y = 0.0 + self.bounds = bounds + self.layer.animateBounds(from: previousBounds, to: self.bounds, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue) default: break } diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index bae497be0b..685c651b28 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -11,6 +11,7 @@ import AccountContext import TelegramStringFormatting import UIKitRuntimeUtils import MediaResources +import AttachmentTextInputPanelNode public enum AttachmentButtonType: Equatable { case gallery @@ -83,6 +84,7 @@ public protocol AttachmentContainable: ViewController { func prepareForReuse() func requestDismiss(completion: @escaping () -> Void) + func shouldDismissImmediately() -> Bool } public extension AttachmentContainable { @@ -101,6 +103,10 @@ public extension AttachmentContainable { func requestDismiss(completion: @escaping () -> Void) { completion() } + + func shouldDismissImmediately() -> Bool { + return true + } } public enum AttachmentMediaPickerSendMode { @@ -162,6 +168,7 @@ public class AttachmentController: ViewController { private let buttons: [AttachmentButtonType] private let initialButton: AttachmentButtonType private let fromMenu: Bool + private let makeEntityInputView: () -> AttachmentTextInputPanelInputView? public var willDismiss: () -> Void = {} public var didDismiss: () -> Void = {} @@ -185,6 +192,7 @@ public class AttachmentController: ViewController { private let dim: ASDisplayNode private let shadowNode: ASImageNode private let container: AttachmentContainer + private let makeEntityInputView: () -> AttachmentTextInputPanelInputView? let panel: AttachmentPanel private var currentType: AttachmentButtonType? @@ -254,8 +262,9 @@ public class AttachmentController: ViewController { private let wrapperNode: ASDisplayNode - init(controller: AttachmentController) { + init(controller: AttachmentController, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) { self.controller = controller + self.makeEntityInputView = makeEntityInputView self.dim = ASDisplayNode() self.dim.alpha = 0.0 @@ -269,7 +278,7 @@ public class AttachmentController: ViewController { self.container = AttachmentContainer() self.container.canHaveKeyboardFocus = true - self.panel = AttachmentPanel(context: controller.context, chatLocation: controller.chatLocation, updatedPresentationData: controller.updatedPresentationData) + self.panel = AttachmentPanel(context: controller.context, chatLocation: controller.chatLocation, updatedPresentationData: controller.updatedPresentationData, makeEntityInputView: makeEntityInputView) self.panel.fromMenu = controller.fromMenu self.panel.isStandalone = controller.isStandalone @@ -312,6 +321,28 @@ public class AttachmentController: ViewController { } } + self.container.shouldCancelPanGesture = { [weak self] in + if let strongSelf = self, let currentController = strongSelf.currentControllers.last { + if !currentController.shouldDismissImmediately() { + return true + } else { + return false + } + } else { + return false + } + } + + self.container.requestDismiss = { [weak self] in + if let strongSelf = self, let currentController = strongSelf.currentControllers.last { + currentController.requestDismiss { [weak self] in + if let strongSelf = self { + strongSelf.controller?.dismiss(animated: true) + } + } + } + } + self.panel.selectionChanged = { [weak self] type in if let strongSelf = self { return strongSelf.switchToController(type) @@ -816,13 +847,14 @@ public class AttachmentController: ViewController { public var getInputContainerNode: () -> (CGFloat, ASDisplayNode, () -> AttachmentController.InputPanelTransition?)? = { return nil } - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, chatLocation: ChatLocation, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, chatLocation: ChatLocation, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) { self.context = context self.updatedPresentationData = updatedPresentationData self.chatLocation = chatLocation self.buttons = buttons self.initialButton = initialButton self.fromMenu = fromMenu + self.makeEntityInputView = makeEntityInputView super.init(navigationBarPresentationData: nil) @@ -850,7 +882,7 @@ public class AttachmentController: ViewController { } open override func loadDisplayNode() { - self.displayNode = Node(controller: self) + self.displayNode = Node(controller: self, makeEntityInputView: self.makeEntityInputView) self.displayNodeDidLoad() } diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 80203f71c7..bdc2e56aca 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -458,6 +458,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { private var presentationInterfaceState: ChatPresentationInterfaceState private var interfaceInteraction: ChatPanelInterfaceInteraction? + private let makeEntityInputView: () -> AttachmentTextInputPanelInputView? + private let containerNode: ASDisplayNode private let backgroundNode: NavigationBackgroundNode private let scrollNode: ASScrollNode @@ -496,9 +498,11 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { var mainButtonPressed: () -> Void = { } - init(context: AccountContext, chatLocation: ChatLocation, updatedPresentationData: (initial: PresentationData, signal: Signal)?) { + init(context: AccountContext, chatLocation: ChatLocation, updatedPresentationData: (initial: PresentationData, signal: Signal)?, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) { self.context = context self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } + + self.makeEntityInputView = makeEntityInputView self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil) @@ -593,7 +597,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -671,6 +675,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, schedule: { [weak textInputPanelNode] in textInputPanelNode?.sendMessage(.schedule) }) + controller.emojiViewProvider = textInputPanelNode.emojiViewProvider strongSelf.presentInGlobalOverlay(controller) }, openScheduledMessages: { }, openPeersNearby: { @@ -691,6 +696,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) @@ -893,7 +900,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { if let strongSelf = self { strongSelf.present(c) } - }) + }, makeEntityInputView: self.makeEntityInputView) textInputPanelNode.interfaceInteraction = self.interfaceInteraction textInputPanelNode.sendMessage = { [weak self] mode in if let strongSelf = self { @@ -1096,7 +1103,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { if textInputPanelNode.frame.width.isZero { panelTransition = .immediate } - let panelHeight = textInputPanelNode.updateLayout(width: layout.size.width, leftInset: insets.left + layout.safeInsets.left, rightInset: insets.right + layout.safeInsets.right, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height / 2.0, isSecondary: false, transition: panelTransition, interfaceState: self.presentationInterfaceState, metrics: layout.metrics) + let panelHeight = textInputPanelNode.updateLayout(width: layout.size.width, leftInset: insets.left + layout.safeInsets.left, rightInset: insets.right + layout.safeInsets.right, bottomInset: 0.0, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height / 2.0, isSecondary: false, transition: panelTransition, interfaceState: self.presentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: false) let panelFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: panelHeight) if textInputPanelNode.frame.width.isZero { textInputPanelNode.frame = panelFrame diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index 8941aaccb8..f4c5b8f379 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -476,17 +476,24 @@ private func formSupportApplePay(_ paymentForm: BotPaymentForm) -> Bool { private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutPaymentMethod?) -> [BotCheckoutPaymentMethod] { var methods: [BotCheckoutPaymentMethod] = [] + var hasApplePay = false if formSupportApplePay(form) && hasApplePaySupport { methods.append(.applePay) + hasApplePay = true + } + + for savedCredentials in form.savedCredentials { + if !methods.contains(.savedCredentials(savedCredentials)) { + methods.append(.savedCredentials(savedCredentials)) + } + } + + if !form.additionalPaymentMethods.isEmpty { + methods.append(contentsOf: form.additionalPaymentMethods.map { .other($0) }) } if let current = current { if !methods.contains(current) { - methods.append(current) - } - } - if let savedCredentials = form.savedCredentials { - if !methods.contains(.savedCredentials(savedCredentials)) { - methods.append(.savedCredentials(savedCredentials)) + methods.insert(current, at: hasApplePay ? 1 : 0) } } return methods @@ -805,9 +812,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz } } - let openNewCard: () -> Void = { [weak self] in + let openNewCard: (String?) -> Void = { [weak self] customUrl in if let strongSelf = self, let paymentForm = strongSelf.paymentFormValue { - if let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "stripe" { + if customUrl == nil, let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "stripe" { guard let paramsData = nativeProvider.params.data(using: .utf8) else { return } @@ -886,7 +893,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz controller?.dismiss() } strongSelf.present(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - } else if let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "smartglocal" { + } else if customUrl == nil, let nativeProvider = paymentForm.nativeProvider, nativeProvider.name == "smartglocal" { guard let paramsData = nativeProvider.params.data(using: .utf8) else { return } @@ -956,7 +963,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz strongSelf.present(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } else { var dismissImpl: (() -> Void)? - let controller = BotCheckoutWebInteractionController(context: context, url: paymentForm.url, intent: .addPaymentMethod({ [weak self] token in + let controller = BotCheckoutWebInteractionController(context: context, url: customUrl ?? paymentForm.url, intent: .addPaymentMethod({ [weak self] token in dismissImpl?() guard let strongSelf = self else { @@ -1055,12 +1062,14 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz strongSelf.controller?.view.endEditing(true) let methods = availablePaymentMethods(form: paymentForm, current: strongSelf.currentPaymentMethod) if methods.isEmpty { - openNewCard() + openNewCard(nil) } else { strongSelf.present(BotCheckoutPaymentMethodSheetController(context: strongSelf.context, currentMethod: strongSelf.currentPaymentMethod, methods: methods, applyValue: { method in applyPaymentMethod(method) }, newCard: { - openNewCard() + openNewCard(nil) + }, otherMethod: { url in + openNewCard(url) }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } } @@ -1099,7 +1108,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz strongSelf.botPeerValue = formAndValidatedInfo.botPeer strongSelf.currentFormInfo = savedInfo strongSelf.currentValidatedFormInfo = formAndValidatedInfo.validatedFormInfo - if let savedCredentials = formAndValidatedInfo.form.savedCredentials { + if let savedCredentials = formAndValidatedInfo.form.savedCredentials.first { strongSelf.currentPaymentMethod = .savedCredentials(savedCredentials) } strongSelf.actionButton.isEnabled = true @@ -1281,6 +1290,22 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz return } + let totalAmount = currentTotalPrice(paymentForm: paymentForm, validatedFormInfo: self.currentValidatedFormInfo, currentShippingOptionId: self.currentShippingOptionId, currentTip: self.currentTipAmount) + let currencyValue = formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency) + + let proceedWithCompletion: (Bool, EngineMessage.Id?) -> Void = { [weak self] success, receiptMessageId in + guard let strongSelf = self else { + return + } + + if success { + strongSelf.dismissAnimated() + strongSelf.completed(currencyValue, receiptMessageId) + } else { + strongSelf.dismissAnimated() + } + } + let credentials: BotPaymentCredentials if let receivedCredentials = receivedCredentials { credentials = receivedCredentials @@ -1416,6 +1441,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz } }) return + case let .other(method): + let _ = method + return } } @@ -1461,9 +1489,6 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz tipAmount = 0 } - let totalAmount = currentTotalPrice(paymentForm: paymentForm, validatedFormInfo: self.currentValidatedFormInfo, currentShippingOptionId: self.currentShippingOptionId, currentTip: self.currentTipAmount) - let currencyValue = formatCurrencyAmount(totalAmount, currency: paymentForm.invoice.currency) - self.payDisposable.set((self.context.engine.payments.sendBotPaymentForm(source: self.source, formId: paymentForm.id, validatedInfoId: self.currentValidatedFormInfo?.id, shippingOptionId: self.currentShippingOptionId, tipAmount: tipAmount, credentials: credentials) |> deliverOnMainQueue).start(next: { [weak self] result in if let strongSelf = self { strongSelf.inProgressDimNode.isUserInteractionEnabled = false @@ -1478,19 +1503,6 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz strongSelf.applePayController = nil applePayController.presentingViewController?.dismiss(animated: true, completion: nil) } - - let proceedWithCompletion: (Bool, EngineMessage.Id?) -> Void = { success, receiptMessageId in - guard let strongSelf = self else { - return - } - - if success { - strongSelf.dismissAnimated() - strongSelf.completed(currencyValue, receiptMessageId) - } else { - strongSelf.dismissAnimated() - } - } switch result { case let .done(receiptMessageId): diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift index c3f64e00d4..f93c6e9fc6 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift @@ -17,6 +17,7 @@ enum BotCheckoutPaymentMethod: Equatable { case savedCredentials(BotPaymentSavedCredentials) case webToken(BotCheckoutPaymentWebToken) case applePay + case other(BotPaymentMethod) var title: String { switch self { @@ -29,6 +30,8 @@ enum BotCheckoutPaymentMethod: Equatable { return token.title case .applePay: return "Apple Pay" + case let .other(method): + return method.title } } } @@ -36,7 +39,7 @@ enum BotCheckoutPaymentMethod: Equatable { final class BotCheckoutPaymentMethodSheetController: ActionSheetController { private var presentationDisposable: Disposable? - init(context: AccountContext, currentMethod: BotCheckoutPaymentMethod?, methods: [BotCheckoutPaymentMethod], applyValue: @escaping (BotCheckoutPaymentMethod) -> Void, newCard: @escaping () -> Void) { + init(context: AccountContext, currentMethod: BotCheckoutPaymentMethod?, methods: [BotCheckoutPaymentMethod], applyValue: @escaping (BotCheckoutPaymentMethod) -> Void, newCard: @escaping () -> Void, otherMethod: @escaping (String) -> Void) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } let strings = presentationData.strings @@ -68,6 +71,9 @@ final class BotCheckoutPaymentMethodSheetController: ActionSheetController { case .applePay: title = "Apple Pay" icon = UIImage(bundleImageName: "Bot Payments/ApplePayLogo")?.precomposed() + case let .other(method): + title = method.title + icon = nil } let value: Bool? if let currentMethod = currentMethod { @@ -76,7 +82,11 @@ final class BotCheckoutPaymentMethodSheetController: ActionSheetController { value = nil } items.append(BotCheckoutPaymentMethodItem(title: title, icon: icon, value: value, action: { [weak self] _ in - applyValue(method) + if case let .other(method) = method { + otherMethod(method.url) + } else { + applyValue(method) + } self?.dismissAnimated() })) } diff --git a/submodules/BotPaymentsUI/Sources/TipEditController.swift b/submodules/BotPaymentsUI/Sources/TipEditController.swift index 59725defe9..e79b2f3405 100644 --- a/submodules/BotPaymentsUI/Sources/TipEditController.swift +++ b/submodules/BotPaymentsUI/Sources/TipEditController.swift @@ -445,7 +445,7 @@ func tipEditController(sharedContext: SharedAccountContext, account: Account, fo controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.inputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller] animated in diff --git a/submodules/BuildConfig/BUILD b/submodules/BuildConfig/BUILD index 83ee53988e..10c5c92dbb 100644 --- a/submodules/BuildConfig/BUILD +++ b/submodules/BuildConfig/BUILD @@ -7,7 +7,6 @@ load( "telegram_is_appstore_build", "telegram_appstore_id", "telegram_app_specific_url_scheme", - "telegram_premium_iap_product_id", ) objc_library( @@ -26,7 +25,6 @@ objc_library( "-DAPP_CONFIG_IS_APPSTORE_BUILD={}".format(telegram_is_appstore_build), "-DAPP_CONFIG_APPSTORE_ID={}".format(telegram_appstore_id), "-DAPP_SPECIFIC_URL_SCHEME=\\\"{}\\\"".format(telegram_app_specific_url_scheme), - "-DAPP_CONFIG_PREMIUM_IAP_PRODUCT_ID=\\\"{}\\\"".format(telegram_premium_iap_product_id), ], hdrs = glob([ "PublicHeaders/**/*.h", diff --git a/submodules/BuildConfig/PublicHeaders/BuildConfig/BuildConfig.h b/submodules/BuildConfig/PublicHeaders/BuildConfig/BuildConfig.h index a433870b93..d735dd74bc 100644 --- a/submodules/BuildConfig/PublicHeaders/BuildConfig/BuildConfig.h +++ b/submodules/BuildConfig/PublicHeaders/BuildConfig/BuildConfig.h @@ -18,7 +18,6 @@ @property (nonatomic, readonly) bool isAppStoreBuild; @property (nonatomic, readonly) int64_t appStoreId; @property (nonatomic, strong, readonly) NSString * _Nonnull appSpecificUrlScheme; -@property (nonatomic, strong, readonly) NSString * _Nonnull premiumIAPProductId; + (DeviceSpecificEncryptionParameters * _Nonnull)deviceSpecificEncryptionParameters:(NSString * _Nonnull)rootPath baseAppBundleId:(NSString * _Nonnull)baseAppBundleId; - (NSData * _Nullable)bundleDataWithAppToken:(NSData * _Nullable)appToken signatureDict:(NSDictionary * _Nullable)signatureDict; diff --git a/submodules/BuildConfig/Sources/BuildConfig.m b/submodules/BuildConfig/Sources/BuildConfig.m index a589f33372..3dde1749ae 100644 --- a/submodules/BuildConfig/Sources/BuildConfig.m +++ b/submodules/BuildConfig/Sources/BuildConfig.m @@ -185,10 +185,6 @@ API_AVAILABLE(ios(10)) return @(APP_SPECIFIC_URL_SCHEME); } -- (NSString *)premiumIAPProductId { - return @(APP_CONFIG_PREMIUM_IAP_PRODUCT_ID); -} - + (NSString * _Nullable)bundleSeedId { NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass, diff --git a/submodules/ChatListUI/BUILD b/submodules/ChatListUI/BUILD index b5d9a7f70a..a88150a88e 100644 --- a/submodules/ChatListUI/BUILD +++ b/submodules/ChatListUI/BUILD @@ -71,6 +71,9 @@ swift_library( "//submodules/PremiumUI:PremiumUI", "//submodules/TelegramUniversalVideoContent:TelegramUniversalVideoContent", "//submodules/Components/HierarchyTrackingLayer:HierarchyTrackingLayer", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer", + "//submodules/TelegramUI/Components/TextNodeWithEntities", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 8cd265b4c0..02ed9d2d8d 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -91,7 +91,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } @@ -661,6 +661,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController return } let animation: LottieAnimationComponent.AnimationItem? + let colors: [String: UIColor] let progressValue: Double? switch state { case let .downloading(progress): @@ -668,13 +669,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController animation = LottieAnimationComponent.AnimationItem( name: "anim_search_downloading", - colors: [ - "Oval.Ellipse 1.Stroke 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Arrow1.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Arrow2.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - ], mode: .animating(loop: true) ) + colors = [ + "Oval.Ellipse 1.Stroke 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Arrow1.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Arrow2.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + ] progressValue = progress strongSelf.clearUnseenDownloadsTimer?.invalidate() @@ -684,18 +685,18 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController animation = LottieAnimationComponent.AnimationItem( name: "anim_search_downloaded", - colors: [ - "Fill 2.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Mask1.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Mask2.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Arrow3.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Fill.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Oval.Ellipse 1.Stroke 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Arrow1.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, - "Arrow2.Union.Fill 1": strongSelf.presentationData.theme.rootController.navigationSearchBar.inputFillColor.blitOver(strongSelf.presentationData.theme.rootController.navigationBar.opaqueBackgroundColor, alpha: 1.0), - ], mode: .animating(loop: false) ) + colors = [ + "Fill 2.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Mask1.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Mask2.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Arrow3.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Fill.Ellipse 1.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Oval.Ellipse 1.Stroke 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Arrow1.Union.Fill 1": strongSelf.presentationData.theme.list.itemAccentColor, + "Arrow2.Union.Fill 1": strongSelf.presentationData.theme.rootController.navigationSearchBar.inputFillColor.blitOver(strongSelf.presentationData.theme.rootController.navigationBar.opaqueBackgroundColor, alpha: 1.0), + ] progressValue = 1.0 if strongSelf.clearUnseenDownloadsTimer == nil { @@ -718,6 +719,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.hasDownloads = hasDownloadsValue animation = nil + colors = [:] progressValue = nil strongSelf.clearUnseenDownloadsTimer?.invalidate() @@ -728,6 +730,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let contentComponent = AnyComponent(ZStack([ AnyComponentWithIdentity(id: 0, component: AnyComponent(LottieAnimationComponent( animation: animation, + colors: colors, size: CGSize(width: 24.0, height: 24.0) ))), AnyComponentWithIdentity(id: 1, component: AnyComponent(ProgressIndicatorComponent( diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index f455761877..ae0d5b8e8f 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -180,7 +180,7 @@ private final class ChatListShimmerNode: ASDisplayNode { let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] - let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: context, activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in gesture?.cancel() }, present: { _ in }) @@ -206,7 +206,8 @@ private final class ChatListShimmerNode: ASDisplayNode { media: [], peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) let readState = EnginePeerReadCounters() diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 607242ad01..000eeaa071 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -1210,7 +1210,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } } } @@ -1412,7 +1412,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index bb8cff58bd..206e4f3eb1 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -1691,7 +1691,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } - let chatListInteraction = ChatListNodeInteraction(activateSearch: { + let chatListInteraction = ChatListNodeInteraction(context: context, activateSearch: { }, peerSelected: { [weak self] peer, chatPeer, _ in interaction.dismissInput() interaction.openPeer(peer, chatPeer, false) @@ -2924,7 +2924,7 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { let timestamp1: Int32 = 100000 var peers: [EnginePeer.Id: EnginePeer] = [:] peers[peer1.id] = peer1 - let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: context, activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in gesture?.cancel() }, present: { _ in }) @@ -2952,7 +2952,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { media: [], peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) let readState = EnginePeerReadCounters() return ChatListItem(presentationData: chatListPresentationData, context: context, peerGroupId: .root, filterData: nil, index: EngineChatList.Item.Index(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1)), content: .peer(messages: [message], peer: EngineRenderedPeer(peer: peer1), combinedReadState: readState, isRemovedFromTotalUnreadCount: false, presence: nil, hasUnseenMentions: false, hasUnseenReactions: false, draftState: nil, inputActivities: nil, promoInfo: nil, ignoreUnreadBadge: false, displayAsMessage: false, hasFailedMessages: false), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction) @@ -2981,7 +2982,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { media: media, peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: true, isGlobalSearchResult: true) @@ -3008,7 +3010,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { media: media, peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true) @@ -3035,7 +3038,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { media: media, peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true) @@ -3062,7 +3066,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode { media: media, peers: peers, associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 7aff6992c1..564b0569a5 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -24,19 +24,25 @@ import TelegramUniversalVideoContent import UniversalMediaPlayer import GalleryUI import HierarchyTrackingLayer +import TextNodeWithEntities public enum ChatListItemContent { public final class DraftState: Equatable { let text: String + let entities: [MessageTextEntity] - public init(text: String) { - self.text = text + public init(draft: EngineChatList.Draft) { + self.text = draft.text + self.entities = draft.entities } public static func ==(lhs: DraftState, rhs: DraftState) -> Bool { if lhs.text != rhs.text { return false } + if lhs.entities != rhs.entities { + return false + } return true } } @@ -440,7 +446,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let authorNode: TextNode let measureNode: TextNode private var currentItemHeight: CGFloat? - let textNode: TextNode + let textNode: TextNodeWithEntities var dustNode: InvisibleInkDustNode? let inputActivitiesNode: ChatListInputActivitiesNode let dateNode: TextNode @@ -550,7 +556,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else { result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage } - let (_, initialHideAuthor, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) + let (_, initialHideAuthor, messageText, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author { result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)" } @@ -584,7 +590,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else { result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage } - let (_, initialHideAuthor, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) + let (_, initialHideAuthor, messageText, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author { result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)" } @@ -624,6 +630,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { self.videoLoopCount = 0 } self.updateVideoVisibility() + + self.textNode.visibilityRect = self.visibilityStatus ? CGRect.infinite : nil } } } @@ -663,9 +671,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { self.authorNode.isUserInteractionEnabled = false self.authorNode.displaysAsynchronously = true - self.textNode = TextNode() - self.textNode.isUserInteractionEnabled = false - self.textNode.displaysAsynchronously = true + self.textNode = TextNodeWithEntities() + self.textNode.textNode.isUserInteractionEnabled = false + self.textNode.textNode.displaysAsynchronously = true self.inputActivitiesNode = ChatListInputActivitiesNode() self.inputActivitiesNode.isUserInteractionEnabled = false @@ -707,7 +715,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { self.contextContainer.addSubnode(self.titleNode) self.contextContainer.addSubnode(self.authorNode) - self.contextContainer.addSubnode(self.textNode) + self.contextContainer.addSubnode(self.textNode.textNode) self.contextContainer.addSubnode(self.dateNode) self.contextContainer.addSubnode(self.statusNode) self.contextContainer.addSubnode(self.pinnedIconNode) @@ -918,7 +926,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { func asyncLayout() -> (_ item: ChatListItem, _ params: ListViewItemLayoutParams, _ first: Bool, _ last: Bool, _ firstWithHeader: Bool, _ nextIsPinned: Bool) -> (ListViewItemNodeLayout, (Bool, Bool) -> Void) { let dateLayout = TextNode.asyncLayout(self.dateNode) - let textLayout = TextNode.asyncLayout(self.textNode) + let textLayout = TextNodeWithEntities.asyncLayout(self.textNode) let titleLayout = TextNode.asyncLayout(self.titleNode) let authorLayout = TextNode.asyncLayout(self.authorNode) let makeMeasureLayout = TextNode.asyncLayout(self.measureNode) @@ -1087,7 +1095,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let leftInset: CGFloat = params.leftInset + avatarLeftInset enum ContentData { - case chat(itemPeer: EngineRenderedPeer, peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?) + case chat(itemPeer: EngineRenderedPeer, peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?) case group(peers: [EngineChatList.GroupItem.Item]) } @@ -1096,7 +1104,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { var hideAuthor = false switch contentPeer { case let .chat(itemPeer): - var (peer, initialHideAuthor, messageText, spoilers) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup) + var (peer, initialHideAuthor, messageText, spoilers, customEmojiRanges) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup) if case let .psa(_, maybePsaText) = promoInfo, let psaText = maybePsaText { initialHideAuthor = true @@ -1117,7 +1125,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { break } - contentData = .chat(itemPeer: itemPeer, peer: peer, hideAuthor: hideAuthor, messageText: messageText, spoilers: spoilers) + contentData = .chat(itemPeer: itemPeer, peer: peer, hideAuthor: hideAuthor, messageText: messageText, spoilers: spoilers, customEmojiRanges: customEmojiRanges) hideAuthor = initialHideAuthor case let .group(groupPeers): contentData = .group(peers: groupPeers) @@ -1148,7 +1156,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { var contentImageSpecs: [(message: EngineMessage, media: EngineMedia, size: CGSize)] = [] switch contentData { - case let .chat(itemPeer, _, _, text, spoilers): + case let .chat(itemPeer, _, _, text, spoilers, customEmojiRanges): var isUser = false if case .user = itemPeer.chatMainPeer { isUser = true @@ -1177,6 +1185,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else { if let spoilers = spoilers, !spoilers.isEmpty { messageText = text + } else if let customEmojiRanges = customEmojiRanges, !customEmojiRanges.isEmpty { + messageText = text } else { messageText = foldLineBreaks(text) } @@ -1186,11 +1196,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if inlineAuthorPrefix == nil, let draftState = draftState { hasDraft = true authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor) - - let draftText: String = draftState.text - attributedText = NSAttributedString(string: foldLineBreaks(draftText.replacingOccurrences(of: "\n\n", with: " ")), font: textFont, textColor: theme.messageTextColor) - } else if let message = messages.last { + let draftText = stringWithAppliedEntities(draftState.text, entities: draftState.entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil) + + attributedText = foldLineBreaks(draftText) + } else if let message = messages.first { var composedString: NSMutableAttributedString if let peerText = peerText { @@ -1198,19 +1208,27 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } let entities = (message._asMessage().textEntitiesAttribute?.entities ?? []).filter { entity in - if case .Spoiler = entity.type { + switch entity.type { + case .Spoiler, .CustomEmoji: return true - } else { + default: return false } } let messageString: NSAttributedString if !message.text.isEmpty && entities.count > 0 { - messageString = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: authorAttributedString == nil ? 2 : 1), entities: entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) - } else if let spoilers = spoilers { + messageString = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: authorAttributedString == nil ? 2 : 1), entities: entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message._asMessage()) + } else if spoilers != nil || customEmojiRanges != nil { let mutableString = NSMutableAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor) - for range in spoilers { - mutableString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true, range: range) + if let spoilers = spoilers { + for range in spoilers { + mutableString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true, range: range) + } + } + if let customEmojiRanges = customEmojiRanges { + for (range, attribute) in customEmojiRanges { + mutableString.addAttribute(ChatTextInputAttributes.customEmoji, value: attribute, range: range) + } } messageString = mutableString } else { @@ -1259,8 +1277,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { attributedText = composedString - - var displayMediaPreviews = true if message._asMessage().containsSecretMedia { displayMediaPreviews = false @@ -1350,7 +1366,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } switch contentData { - case let .chat(itemPeer, _, _, _, _): + case let .chat(itemPeer, _, _, _, _, _): if let message = messages.last, case let .user(author) = message.author, displayAsMessage { titleAttributedString = NSAttributedString(string: author.id == account.peerId ? item.presentationData.strings.DialogList_You : EnginePeer.user(author).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: titleFont, textColor: theme.titleColor) } else if isPeerGroup { @@ -1787,7 +1803,15 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let _ = measureApply() let _ = dateApply() - let _ = textApply() + + let _ = textApply(TextNodeWithEntities.Arguments( + context: item.context, + cache: item.interaction.animationCache, + renderer: item.interaction.animationRenderer, + placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads + )) + let _ = authorApply() let _ = titleApply() let _ = badgeApply(animateBadges, !isMuted) @@ -1862,7 +1886,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let authorNodeFrame = CGRect(origin: CGPoint(x: contentRect.origin.x - 1.0, y: contentRect.minY + titleLayout.size.height), size: authorLayout.size) strongSelf.authorNode.frame = authorNodeFrame let textNodeFrame = CGRect(origin: CGPoint(x: contentRect.origin.x - 1.0, y: contentRect.minY + titleLayout.size.height - 1.0 + UIScreenPixel + (authorLayout.size.height.isZero ? 0.0 : (authorLayout.size.height - 3.0))), size: textLayout.size) - strongSelf.textNode.frame = textNodeFrame + strongSelf.textNode.textNode.frame = textNodeFrame if !textLayout.spoilers.isEmpty { let dustNode: InvisibleInkDustNode @@ -1872,7 +1896,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { dustNode = InvisibleInkDustNode(textNode: nil) dustNode.isUserInteractionEnabled = false strongSelf.dustNode = dustNode - strongSelf.contextContainer.insertSubnode(dustNode, aboveSubnode: strongSelf.textNode) + strongSelf.contextContainer.insertSubnode(dustNode, aboveSubnode: strongSelf.textNode.textNode) } dustNode.update(size: textNodeFrame.size, color: theme.messageTextColor, textColor: theme.messageTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 0.0, dy: 1.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 0.0, dy: 1.0) }) dustNode.frame = textNodeFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0) @@ -1901,13 +1925,13 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if strongSelf.inputActivitiesNode.alpha.isZero { strongSelf.inputActivitiesNode.alpha = 1.0 - strongSelf.textNode.alpha = 0.0 + strongSelf.textNode.textNode.alpha = 0.0 strongSelf.authorNode.alpha = 0.0 strongSelf.dustNode?.alpha = 0.0 if animated || animateContent { strongSelf.inputActivitiesNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) - strongSelf.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) + strongSelf.textNode.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) strongSelf.authorNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) strongSelf.dustNode?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15) } @@ -1915,7 +1939,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else { if !strongSelf.inputActivitiesNode.alpha.isZero { strongSelf.inputActivitiesNode.alpha = 0.0 - strongSelf.textNode.alpha = 1.0 + strongSelf.textNode.textNode.alpha = 1.0 strongSelf.authorNode.alpha = 1.0 strongSelf.dustNode?.alpha = 1.0 if animated || animateContent { @@ -1924,7 +1948,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { strongSelf.inputActivitiesNode.removeFromSupernode() } }) - strongSelf.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) + strongSelf.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) strongSelf.authorNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) strongSelf.dustNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) } else { @@ -1983,7 +2007,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let titlePosition = strongSelf.titleNode.position transition.animatePosition(node: strongSelf.titleNode, from: CGPoint(x: titlePosition.x - contentDelta.x, y: titlePosition.y - contentDelta.y)) - transition.animatePositionAdditive(node: strongSelf.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y)) + transition.animatePositionAdditive(node: strongSelf.textNode.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y)) if let dustNode = strongSelf.dustNode { transition.animatePositionAdditive(node: dustNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y)) } @@ -1995,7 +2019,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if crossfadeContent { strongSelf.authorNode.recursivelyEnsureDisplaySynchronously(true) strongSelf.titleNode.recursivelyEnsureDisplaySynchronously(true) - strongSelf.textNode.recursivelyEnsureDisplaySynchronously(true) + strongSelf.textNode.textNode.recursivelyEnsureDisplaySynchronously(true) } var nextTitleIconOrigin: CGFloat = contentRect.origin.x + titleLayout.size.width + 3.0 + titleOffset @@ -2245,9 +2269,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { transition.updateFrame(node: self.inputActivitiesNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x, y: self.inputActivitiesNode.frame.minY), size: self.inputActivitiesNode.bounds.size)) - var textFrame = self.textNode.frame + var textFrame = self.textNode.textNode.frame textFrame.origin.x = contentRect.origin.x - transition.updateFrameAdditive(node: self.textNode, frame: textFrame) + transition.updateFrameAdditive(node: self.textNode.textNode, frame: textFrame) if let dustNode = self.dustNode { transition.updateFrameAdditive(node: dustNode, frame: textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0)) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift index fdcb30c450..8ed87f6c69 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift @@ -4,6 +4,7 @@ import TelegramPresentationData import TelegramUIPreferences import TelegramStringFormatting import LocalizedPeerData +import TextFormat private enum MessageGroupType { case photos @@ -44,7 +45,7 @@ private func messageGroupType(messages: [EngineMessage]) -> MessageGroupType { return currentType } -public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?) { +public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?) { let peer: EnginePeer? let message = messages.last @@ -52,6 +53,7 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: var hideAuthor = false var messageText: String var spoilers: [NSRange]? + var customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]? if let message = message { if let messageMain = messageMainPeer(message) { peer = messageMain @@ -269,13 +271,14 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: } default: hideAuthor = true - if let (text, textSpoilers) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { + if let (text, textSpoilers, customEmojiRangesValue) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { messageText = text spoilers = textSpoilers + customEmojiRanges = customEmojiRangesValue } } case _ as TelegramMediaExpiredContent: - if let (text, _) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { + if let (text, _, _) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { messageText = text } case let poll as TelegramMediaPoll: @@ -314,5 +317,5 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: } } - return (peer, hideAuthor, messageText, spoilers) + return (peer, hideAuthor, messageText, spoilers, customEmojiRanges) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index ef7a2a5ecc..ba7c393edf 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -14,6 +14,9 @@ import ItemListUI import SearchUI import ChatListSearchItemHeader import PremiumUI +import AnimationCache +import MultiAnimationRenderer +import Postbox public enum ChatListNodeMode { case chatList @@ -75,7 +78,10 @@ public final class ChatListNodeInteraction { public var searchTextHighightState: String? var highlightedChatLocation: ChatListHighlightedLocation? - public init(activateSearch: @escaping () -> Void, peerSelected: @escaping (EnginePeer, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (EnginePeer) -> Void, togglePeerSelected: @escaping (EnginePeer) -> Void, togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (EnginePeer, EngineMessage, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (EngineChatList.Group) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, setItemPinned: @escaping (EngineChatList.PinnedItem.Id, Bool) -> Void, setPeerMuted: @escaping (EnginePeer.Id, Bool) -> Void, deletePeer: @escaping (EnginePeer.Id, Bool) -> Void, updatePeerGrouping: @escaping (EnginePeer.Id, Bool) -> Void, togglePeerMarkedUnread: @escaping (EnginePeer.Id, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (EnginePeer.Id) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) { + let animationCache: AnimationCache + let animationRenderer: MultiAnimationRenderer + + public init(context: AccountContext, activateSearch: @escaping () -> Void, peerSelected: @escaping (EnginePeer, EnginePeer?, ChatListNodeEntryPromoInfo?) -> Void, disabledPeerSelected: @escaping (EnginePeer) -> Void, togglePeerSelected: @escaping (EnginePeer) -> Void, togglePeersSelection: @escaping ([PeerEntry], Bool) -> Void, additionalCategorySelected: @escaping (Int) -> Void, messageSelected: @escaping (EnginePeer, EngineMessage, ChatListNodeEntryPromoInfo?) -> Void, groupSelected: @escaping (EngineChatList.Group) -> Void, addContact: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, setItemPinned: @escaping (EngineChatList.PinnedItem.Id, Bool) -> Void, setPeerMuted: @escaping (EnginePeer.Id, Bool) -> Void, deletePeer: @escaping (EnginePeer.Id, Bool) -> Void, updatePeerGrouping: @escaping (EnginePeer.Id, Bool) -> Void, togglePeerMarkedUnread: @escaping (EnginePeer.Id, Bool) -> Void, toggleArchivedFolderHiddenByDefault: @escaping () -> Void, hidePsa: @escaping (EnginePeer.Id) -> Void, activateChatPreview: @escaping (ChatListItem, ASDisplayNode, ContextGesture?) -> Void, present: @escaping (ViewController) -> Void) { self.activateSearch = activateSearch self.peerSelected = peerSelected self.disabledPeerSelected = disabledPeerSelected @@ -95,6 +101,11 @@ public final class ChatListNodeInteraction { self.hidePsa = hidePsa self.activateChatPreview = activateChatPreview self.present = present + + self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + self.animationRenderer = MultiAnimationRendererImpl() } } @@ -733,7 +744,7 @@ public final class ChatListNode: ListView { self.keepMinimalScrollHeightWithTopInset = navigationBarSearchContentHeight - let nodeInteraction = ChatListNodeInteraction(activateSearch: { [weak self] in + let nodeInteraction = ChatListNodeInteraction(context: context, activateSearch: { [weak self] in if let strongSelf = self, let activateSearch = strongSelf.activateSearch { activateSearch() } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift index 742ce753e6..c4095fbfba 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeEntries.swift @@ -325,8 +325,8 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState } var draftState: ChatListItemContent.DraftState? - if let draftText = entry.draftText { - draftState = ChatListItemContent.DraftState(text: draftText) + if let draft = entry.draft { + draftState = ChatListItemContent.DraftState(draft: draft) } result.append(.PeerEntry(index: offsetPinnedIndex(entry.index, offset: pinnedIndexOffset), presentationData: state.presentationData, messages: updatedMessages, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: entry.isMuted, draftState: draftState, peer: entry.renderedPeer, presence: entry.presence, hasUnseenMentions: entry.hasUnseenMentions, hasUnseenReactions: entry.hasUnseenReactions, editing: state.editing, hasActiveRevealControls: entry.index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(entry.index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[entry.index.messageIndex.id.peerId], promoInfo: nil, hasFailedMessages: entry.hasFailed, isContact: entry.isContact)) @@ -380,7 +380,7 @@ func chatListNodeEntriesForView(_ view: EngineChatList, state: ChatListNodeState case let .psa(type, message): promoInfo = .psa(type: type, message: message) } - let draftState = item.item.draftText.flatMap(ChatListItemContent.DraftState.init(text:)) + let draftState = item.item.draft.flatMap(ChatListItemContent.DraftState.init) result.append(.PeerEntry( index: EngineChatList.Item.Index(pinningIndex: pinningIndex, messageIndex: item.item.index.messageIndex), presentationData: state.presentationData, diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 5b2d46fcbb..5e38c1994b 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -46,6 +46,7 @@ public enum ChatPanelSearchNavigationAction { public enum ChatPanelRestrictionInfoSubject { case mediaRecording case stickers + case premiumVoiceMessages } public enum ChatPanelRestrictionInfoDisplayType { @@ -98,7 +99,7 @@ public final class ChatPanelInterfaceInteraction { public let displayVideoUnmuteTip: (CGPoint?) -> Void public let switchMediaRecordingMode: () -> Void public let setupMessageAutoremoveTimeout: () -> Void - public let sendSticker: (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool + public let sendSticker: (FileMediaReference, Bool, UIView, CGRect, CALayer?) -> Bool public let unblockPeer: () -> Void public let pinMessage: (MessageId, ContextControllerProtocol?) -> Void public let unpinMessage: (MessageId, Bool, ContextControllerProtocol?) -> Void @@ -123,7 +124,7 @@ public final class ChatPanelInterfaceInteraction { public let unarchiveChat: () -> Void public let openLinkEditing: () -> Void public let reportPeerIrrelevantGeoLocation: () -> Void - public let displaySlowmodeTooltip: (ASDisplayNode, CGRect) -> Void + public let displaySlowmodeTooltip: (UIView, CGRect) -> Void public let displaySendMessageOptions: (ASDisplayNode, ContextGesture) -> Void public let openScheduledMessages: () -> Void public let displaySearchResultsTooltip: (ASDisplayNode, CGRect) -> Void @@ -144,6 +145,8 @@ public final class ChatPanelInterfaceInteraction { public let displayCopyProtectionTip: (ASDisplayNode, Bool) -> Void public let openWebView: (String, String, Bool, Bool) -> Void public let updateShowWebView: ((Bool) -> Bool) -> Void + public let insertText: (NSAttributedString) -> Void + public let backwardsDeleteText: () -> Void public let chatController: () -> ViewController? public let statuses: ChatPanelInterfaceInteractionStatuses? @@ -192,7 +195,7 @@ public final class ChatPanelInterfaceInteraction { displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, - sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, UIView, CGRect, CALayer?) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void, unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void, @@ -217,7 +220,7 @@ public final class ChatPanelInterfaceInteraction { unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, - displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, + displaySlowmodeTooltip: @escaping (UIView, CGRect) -> Void, displaySendMessageOptions: @escaping (ASDisplayNode, ContextGesture) -> Void, openScheduledMessages: @escaping () -> Void, openPeersNearby: @escaping () -> Void, @@ -238,6 +241,8 @@ public final class ChatPanelInterfaceInteraction { displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void, openWebView: @escaping (String, String, Bool, Bool) -> Void, updateShowWebView: @escaping ((Bool) -> Bool) -> Void, + insertText: @escaping (NSAttributedString) -> Void, + backwardsDeleteText: @escaping () -> Void, chatController: @escaping () -> ViewController?, statuses: ChatPanelInterfaceInteractionStatuses? ) { @@ -331,6 +336,9 @@ public final class ChatPanelInterfaceInteraction { self.displayCopyProtectionTip = displayCopyProtectionTip self.openWebView = openWebView self.updateShowWebView = updateShowWebView + self.insertText = insertText + self.backwardsDeleteText = backwardsDeleteText + self.chatController = chatController self.statuses = statuses } @@ -384,7 +392,7 @@ public final class ChatPanelInterfaceInteraction { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -431,6 +439,8 @@ public final class ChatPanelInterfaceInteraction { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift index f3d36ca415..8260e9fed4 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPresentationInterfaceState.swift @@ -392,6 +392,7 @@ public final class ChatPresentationInterfaceState: Equatable { public let hasPlentyOfMessages: Bool public let isPremium: Bool public let forceInputCommandsHidden: Bool + public let voiceMessagesAvailable: Bool public init(chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, chatLocation: ChatLocation, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?) { self.interfaceState = ChatInterfaceState() @@ -456,9 +457,10 @@ public final class ChatPresentationInterfaceState: Equatable { self.hasPlentyOfMessages = false self.isPremium = false self.forceInputCommandsHidden = false + self.voiceMessagesAvailable = true } - public init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: ChatPinnedMessage?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, presentationReady: Bool, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, autoremoveTimeout: Int32?, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?, reportReason: ReportReason?, showCommands: Bool, hasBotCommands: Bool, showSendAsPeers: Bool, sendAsPeers: [FoundPeer]?, botMenuButton: BotMenuButton, showWebView: Bool, currentSendAsPeerId: PeerId?, copyProtectionEnabled: Bool, hasPlentyOfMessages: Bool, isPremium: Bool, forceInputCommandsHidden: Bool) { + public init(interfaceState: ChatInterfaceState, chatLocation: ChatLocation, renderedPeer: RenderedPeer?, isNotAccessible: Bool, explicitelyCanPinMessages: Bool, contactStatus: ChatContactStatus?, hasBots: Bool, isArchived: Bool, inputTextPanelState: ChatTextInputPanelState, editMessageState: ChatEditInterfaceMessageState?, recordedMediaPreview: ChatRecordedMediaPreview?, inputQueryResults: [ChatPresentationInputQueryKind: ChatPresentationInputQueryResult], inputMode: ChatInputMode, titlePanelContexts: [ChatTitlePanelContext], keyboardButtonsMessage: Message?, pinnedMessageId: MessageId?, pinnedMessage: ChatPinnedMessage?, peerIsBlocked: Bool, peerIsMuted: Bool, peerDiscussionId: PeerId?, peerGeoLocation: PeerGeoLocation?, callsAvailable: Bool, callsPrivate: Bool, slowmodeState: ChatSlowmodeState?, chatHistoryState: ChatHistoryNodeHistoryState?, botStartPayload: String?, urlPreview: (String, TelegramMediaWebpage)?, editingUrlPreview: (String, TelegramMediaWebpage)?, search: ChatSearchData?, searchQuerySuggestionResult: ChatPresentationInputQueryResult?, presentationReady: Bool, chatWallpaper: TelegramWallpaper, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, limitsConfiguration: LimitsConfiguration, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, accountPeerId: PeerId, mode: ChatControllerPresentationMode, hasScheduledMessages: Bool, autoremoveTimeout: Int32?, subject: ChatControllerSubject?, peerNearbyData: ChatPeerNearbyData?, greetingData: ChatGreetingData?, pendingUnpinnedAllMessages: Bool, activeGroupCallInfo: ChatActiveGroupCallInfo?, hasActiveGroupCall: Bool, importState: ChatPresentationImportState?, reportReason: ReportReason?, showCommands: Bool, hasBotCommands: Bool, showSendAsPeers: Bool, sendAsPeers: [FoundPeer]?, botMenuButton: BotMenuButton, showWebView: Bool, currentSendAsPeerId: PeerId?, copyProtectionEnabled: Bool, hasPlentyOfMessages: Bool, isPremium: Bool, forceInputCommandsHidden: Bool, voiceMessagesAvailable: Bool) { self.interfaceState = interfaceState self.chatLocation = chatLocation self.renderedPeer = renderedPeer @@ -521,6 +523,7 @@ public final class ChatPresentationInterfaceState: Equatable { self.hasPlentyOfMessages = hasPlentyOfMessages self.isPremium = isPremium self.forceInputCommandsHidden = forceInputCommandsHidden + self.voiceMessagesAvailable = voiceMessagesAvailable } public static func ==(lhs: ChatPresentationInterfaceState, rhs: ChatPresentationInterfaceState) -> Bool { @@ -722,35 +725,38 @@ public final class ChatPresentationInterfaceState: Equatable { if lhs.forceInputCommandsHidden != rhs.forceInputCommandsHidden { return false } + if lhs.voiceMessagesAvailable != rhs.voiceMessagesAvailable { + return false + } return true } public func updatedInterfaceState(_ f: (ChatInterfaceState) -> ChatInterfaceState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: f(self.interfaceState), chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPeer(_ f: (RenderedPeer?) -> RenderedPeer?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: f(self.renderedPeer), isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedIsNotAccessible(_ isNotAccessible: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedExplicitelyCanPinMessages(_ explicitelyCanPinMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedContactStatus(_ contactStatus: ChatContactStatus?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedHasBots(_ hasBots: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedIsArchived(_ isArchived: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedInputQueryResult(queryKind: ChatPresentationInputQueryKind, _ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { @@ -762,191 +768,195 @@ public final class ChatPresentationInterfaceState: Equatable { inputQueryResults.removeValue(forKey: queryKind) } - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedInputTextPanelState(_ f: (ChatTextInputPanelState) -> ChatTextInputPanelState) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: f(self.inputTextPanelState), editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedEditMessageState(_ editMessageState: ChatEditInterfaceMessageState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedRecordedMediaPreview(_ recordedMediaPreview: ChatRecordedMediaPreview?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedInputMode(_ f: (ChatInputMode) -> ChatInputMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: f(self.inputMode), titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedTitlePanelContext(_ f: ([ChatTitlePanelContext]) -> [ChatTitlePanelContext]) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: f(self.titlePanelContexts), keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedKeyboardButtonsMessage(_ message: Message?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: message, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPinnedMessage(_ pinnedMessage: ChatPinnedMessage?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPeerIsBlocked(_ peerIsBlocked: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPeerIsMuted(_ peerIsMuted: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPeerDiscussionId(_ peerDiscussionId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPeerGeoLocation(_ peerGeoLocation: PeerGeoLocation?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedCallsAvailable(_ callsAvailable: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedCallsPrivate(_ callsPrivate: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedSlowmodeState(_ slowmodeState: ChatSlowmodeState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedBotStartPayload(_ botStartPayload: String?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedChatHistoryState(_ chatHistoryState: ChatHistoryNodeHistoryState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedUrlPreview(_ urlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedEditingUrlPreview(_ editingUrlPreview: (String, TelegramMediaWebpage)?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedSearch(_ search: ChatSearchData?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedSearchQuerySuggestionResult(_ f: (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: f(self.searchQuerySuggestionResult), presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedMode(_ mode: ChatControllerPresentationMode) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPresentationReady(_ presentationReady: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedTheme(_ theme: PresentationTheme) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedStrings(_ strings: PresentationStrings) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedDateTimeFormat(_ dateTimeFormat: PresentationDateTimeFormat) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedChatWallpaper(_ chatWallpaper: TelegramWallpaper) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedBubbleCorners(_ bubbleCorners: PresentationChatBubbleCorners) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedAutoremoveTimeout(_ autoremoveTimeout: Int32?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedPendingUnpinnedAllMessages(_ pendingUnpinnedAllMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedActiveGroupCallInfo(_ activeGroupCallInfo: ChatActiveGroupCallInfo?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedHasActiveGroupCall(_ hasActiveGroupCall: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedImportState(_ importState: ChatPresentationImportState?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedReportReason(_ reportReason: ReportReason?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedShowCommands(_ showCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedHasBotCommands(_ hasBotCommands: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedShowSendAsPeers(_ showSendAsPeers: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedSendAsPeers(_ sendAsPeers: [FoundPeer]?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedCurrentSendAsPeerId(_ currentSendAsPeerId: PeerId?) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedBotMenuButton(_ botMenuButton: BotMenuButton) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedShowWebView(_ showWebView: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedCopyProtectionEnabled(_ copyProtectionEnabled: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedHasPlentyOfMessages(_ hasPlentyOfMessages: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedIsPremium(_ isPremium: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func updatedForceInputCommandsHidden(_ forceInputCommandsHidden: Bool) -> ChatPresentationInterfaceState { - return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: forceInputCommandsHidden) + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: forceInputCommandsHidden, voiceMessagesAvailable: self.voiceMessagesAvailable) + } + + public func updatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> ChatPresentationInterfaceState { + return ChatPresentationInterfaceState(interfaceState: self.interfaceState, chatLocation: self.chatLocation, renderedPeer: self.renderedPeer, isNotAccessible: self.isNotAccessible, explicitelyCanPinMessages: self.explicitelyCanPinMessages, contactStatus: self.contactStatus, hasBots: self.hasBots, isArchived: self.isArchived, inputTextPanelState: self.inputTextPanelState, editMessageState: self.editMessageState, recordedMediaPreview: self.recordedMediaPreview, inputQueryResults: self.inputQueryResults, inputMode: self.inputMode, titlePanelContexts: self.titlePanelContexts, keyboardButtonsMessage: self.keyboardButtonsMessage, pinnedMessageId: self.pinnedMessageId, pinnedMessage: self.pinnedMessage, peerIsBlocked: self.peerIsBlocked, peerIsMuted: self.peerIsMuted, peerDiscussionId: self.peerDiscussionId, peerGeoLocation: self.peerGeoLocation, callsAvailable: self.callsAvailable, callsPrivate: self.callsPrivate, slowmodeState: self.slowmodeState, chatHistoryState: self.chatHistoryState, botStartPayload: self.botStartPayload, urlPreview: self.urlPreview, editingUrlPreview: self.editingUrlPreview, search: self.search, searchQuerySuggestionResult: self.searchQuerySuggestionResult, presentationReady: self.presentationReady, chatWallpaper: self.chatWallpaper, theme: self.theme, strings: self.strings, dateTimeFormat: self.dateTimeFormat, nameDisplayOrder: self.nameDisplayOrder, limitsConfiguration: self.limitsConfiguration, fontSize: self.fontSize, bubbleCorners: self.bubbleCorners, accountPeerId: self.accountPeerId, mode: self.mode, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, subject: self.subject, peerNearbyData: self.peerNearbyData, greetingData: self.greetingData, pendingUnpinnedAllMessages: self.pendingUnpinnedAllMessages, activeGroupCallInfo: self.activeGroupCallInfo, hasActiveGroupCall: self.hasActiveGroupCall, importState: self.importState, reportReason: self.reportReason, showCommands: self.showCommands, hasBotCommands: self.hasBotCommands, showSendAsPeers: self.showSendAsPeers, sendAsPeers: self.sendAsPeers, botMenuButton: self.botMenuButton, showWebView: self.showWebView, currentSendAsPeerId: self.currentSendAsPeerId, copyProtectionEnabled: self.copyProtectionEnabled, hasPlentyOfMessages: self.hasPlentyOfMessages, isPremium: self.isPremium, forceInputCommandsHidden: self.forceInputCommandsHidden, voiceMessagesAvailable: voiceMessagesAvailable) } } diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift index 2e50a789fa..08f5f89fdf 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift @@ -3,13 +3,45 @@ import AccountContext import SwiftSignalKit public enum ChatTextInputAccessoryItem: Equatable { - case keyboard - case stickers(Bool) - case inputButtons + public enum Key: Hashable { + case input + case botInput + case commands + case silentPost + case messageAutoremoveTimeout + case scheduledMessages + } + + public enum InputMode: Hashable { + case keyboard + case stickers + case emoji + case bot + } + case input(isEnabled: Bool, inputMode: InputMode) + case botInput(isEnabled: Bool, inputMode: InputMode) + case commands case silentPost(Bool) case messageAutoremoveTimeout(Int32?) case scheduledMessages + + public var key: Key { + switch self { + case .input: + return .input + case .botInput: + return .botInput + case .commands: + return .commands + case .silentPost: + return .silentPost + case .messageAutoremoveTimeout: + return .messageAutoremoveTimeout + case .scheduledMessages: + return .scheduledMessages + } + } } public final class InstantVideoControllerRecordingStatus { diff --git a/submodules/ChatSendMessageActionUI/BUILD b/submodules/ChatSendMessageActionUI/BUILD index f78a1da76a..51314b168b 100644 --- a/submodules/ChatSendMessageActionUI/BUILD +++ b/submodules/ChatSendMessageActionUI/BUILD @@ -19,6 +19,8 @@ swift_library( "//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState", "//submodules/ContextUI:ContextUI", "//submodules/AppBundle:AppBundle", + "//submodules/TextFormat:TextFormat", + "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift index 5f2b3d4077..50a0b0858e 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift @@ -8,6 +8,7 @@ import AccountContext import ContextUI import TelegramCore import ChatPresentationInterfaceState +import TextFormat public final class ChatSendMessageActionSheetController: ViewController { private var controllerNode: ChatSendMessageActionSheetControllerNode { @@ -32,6 +33,8 @@ public final class ChatSendMessageActionSheetController: ViewController { private var validLayout: ContainerViewLayout? private let hapticFeedback = HapticFeedback() + + public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, interfaceState: ChatPresentationInterfaceState, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool = false, completion: @escaping () -> Void, sendMessage: @escaping (Bool) -> Void, schedule: @escaping () -> Void) { self.context = context @@ -54,7 +57,9 @@ public final class ChatSendMessageActionSheetController: ViewController { |> deliverOnMainQueue).start(next: { [weak self] presentationData in if let strongSelf = self { strongSelf.presentationData = presentationData - strongSelf.controllerNode.updatePresentationData(presentationData) + if strongSelf.isNodeLoaded { + strongSelf.controllerNode.updatePresentationData(presentationData) + } } }) @@ -79,13 +84,18 @@ public final class ChatSendMessageActionSheetController: ViewController { var reminders = false var isSecret = false var canSchedule = false + var hasEntityKeyboard = false if case let .peer(peerId) = self.interfaceState.chatLocation { reminders = peerId == context.account.peerId isSecret = peerId.namespace == Namespaces.Peer.SecretChat canSchedule = !isSecret } - self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, send: { [weak self] in + if case .media = self.interfaceState.inputMode { + hasEntityKeyboard = true + } + + self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, forwardedCount: forwardedCount, hasEntityKeyboard: hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in self?.sendMessage(false) self?.dismiss(cancel: false) }, sendSilently: { [weak self] in diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index e76b1d04a2..3164dcec7c 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -9,6 +9,8 @@ import TelegramPresentationData import AccountContext import AppBundle import ContextUI +import TextFormat +import EmojiTextAttachmentView private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 @@ -158,6 +160,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private let textInputNode: EditableTextNode private let attachment: Bool private let forwardedCount: Int? + private let hasEntityKeyboard: Bool private let send: (() -> Void)? private let cancel: (() -> Void)? @@ -175,6 +178,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private let toMessageTextNode: EditableTextNode private let scrollNode: ASScrollNode + private var fromCustomEmojiContainerView: CustomEmojiContainerView? + private var toCustomEmojiContainerView: CustomEmojiContainerView? + private var validLayout: ContainerViewLayout? private var sendButtonFrame: CGRect { @@ -183,7 +189,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private var animateInputField = false - init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { + private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? + + init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { self.context = context self.presentationData = presentationData self.sourceSendButton = sourceSendButton @@ -191,6 +199,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.textInputNode = textInputNode self.attachment = attachment self.forwardedCount = forwardedCount + self.hasEntityKeyboard = hasEntityKeyboard + self.emojiViewProvider = emojiViewProvider self.send = send self.cancel = cancel @@ -348,6 +358,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } } + func updateTextContents() { + var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] + + let textInputNode = self.fromMessageTextNode + if let attributedText = textInputNode.attributedText { + let beginning = textInputNode.textView.beginningOfDocument + attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in + if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + if let start = textInputNode.textView.position(from: beginning, offset: range.location), let end = textInputNode.textView.position(from: start, offset: range.length), let textRange = textInputNode.textView.textRange(from: start, to: end) { + let textRects = textInputNode.textView.selectionRects(for: textRange) + for textRect in textRects { + customEmojiRects.append((textRect.rect, value)) + break + } + } + } + }) + } + + self.updateTextContents(rects: customEmojiRects, textInputNode: self.fromMessageTextNode, from: true) + self.updateTextContents(rects: customEmojiRects, textInputNode: self.toMessageTextNode, from: false) + } + + func updateTextContents(rects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)], textInputNode: EditableTextNode, from: Bool) { + if !rects.isEmpty { + let customEmojiContainerView: CustomEmojiContainerView + if from, let current = self.fromCustomEmojiContainerView { + customEmojiContainerView = current + } else if !from, let current = self.toCustomEmojiContainerView { + customEmojiContainerView = current + } else { + customEmojiContainerView = CustomEmojiContainerView(emojiViewProvider: { [weak self] emoji in + guard let strongSelf = self, let emojiViewProvider = strongSelf.emojiViewProvider else { + return nil + } + return emojiViewProvider(emoji) + }) + customEmojiContainerView.isUserInteractionEnabled = false + textInputNode.textView.addSubview(customEmojiContainerView) + if from { + self.fromCustomEmojiContainerView = customEmojiContainerView + } else { + self.toCustomEmojiContainerView = customEmojiContainerView + } + } + + customEmojiContainerView.update(emojiRects: rects) + } else { + if from, let customEmojiContainerView = self.fromCustomEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.fromCustomEmojiContainerView = nil + } else if !from, let customEmojiContainerView = self.toCustomEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.fromCustomEmojiContainerView = nil + } + } + } + func updatePresentationData(_ presentationData: PresentationData) { guard presentationData.theme !== self.presentationData.theme else { return @@ -422,7 +490,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let fromFrame = CGRect(origin: CGPoint(), size: CGSize(width: initialWidth, height: self.textFieldFrame.height + 2.0)) let delta = (fromFrame.height - self.messageClipNode.bounds.height) / 2.0 - let inputHeight = layout.inputHeight ?? 0.0 + var inputHeight = layout.inputHeight ?? 0.0 + if self.hasEntityKeyboard { + inputHeight = layout.standardInputHeight + } + var clipDelta = delta if inputHeight.isZero || layout.isNonExclusive { clipDelta -= self.contentContainerNode.frame.height + 16.0 @@ -452,6 +524,10 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let springDamping: CGFloat = 104.0 self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping) self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true) + + Queue.mainQueue().after(0.01, { + self.updateTextContents() + }) } func animateOut(cancel: Bool, completion: @escaping () -> Void) { @@ -531,7 +607,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let delta = (toFrame.height - self.messageClipNode.bounds.height) / 2.0 if cancel && self.animateInputField { - let inputHeight = layout.inputHeight ?? 0.0 + var inputHeight = layout.inputHeight ?? 0.0 + if self.hasEntityKeyboard { + inputHeight = layout.standardInputHeight + } + var clipDelta = delta if inputHeight.isZero || layout.isNonExclusive { clipDelta -= self.contentContainerNode.frame.height + 16.0 @@ -589,8 +669,12 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let menuHeightWithInset = contentSize.height + 16.0 - let insets = layout.insets(options: [.statusBar, .input]) - let inputHeight = layout.inputHeight ?? 0.0 + var insets = layout.insets(options: [.statusBar, .input]) + var inputHeight = layout.inputHeight ?? 0.0 + if self.hasEntityKeyboard { + insets.bottom = max(insets.bottom, layout.standardInputHeight) + inputHeight = layout.standardInputHeight + } let contentOffset = self.scrollNode.view.contentOffset.y @@ -656,6 +740,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, var textFrame = self.textFieldFrame textFrame.origin = CGPoint(x: 13.0, y: 6.0 - UIScreenPixel) textFrame.size.height = self.textInputNode.textView.contentSize.height + textFrame.size.width -= self.textInputNode.textContainerInset.right if self.textInputNode.isRTL { textFrame.origin.x -= messageOriginDelta @@ -676,3 +761,64 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.send?() } } + +final class CustomEmojiContainerView: UIView { + private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView? + + private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:] + + init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) { + self.emojiViewProvider = emojiViewProvider + + super.init(frame: CGRect()) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + func update(emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) { + var nextIndexById: [Int64: Int] = [:] + + var validKeys = Set() + for (rect, emoji) in emojiRects { + let index: Int + if let nextIndex = nextIndexById[emoji.fileId] { + index = nextIndex + } else { + index = 0 + } + nextIndexById[emoji.fileId] = index + 1 + + let key = InlineStickerItemLayer.Key(id: emoji.fileId, index: index) + + let view: UIView + if let current = self.emojiLayers[key] { + view = current + } else if let newView = self.emojiViewProvider(emoji) { + view = newView + self.addSubview(newView) + self.emojiLayers[key] = view + } else { + continue + } + + let size = CGSize(width: 24.0, height: 24.0) + + view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size) + + validKeys.insert(key) + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, view) in self.emojiLayers { + if !validKeys.contains(key) { + removeKeys.append(key) + view.removeFromSuperview() + } + } + for key in removeKeys { + self.emojiLayers.removeValue(forKey: key) + } + } +} diff --git a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift index e5bd678db3..0206d8f688 100644 --- a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift +++ b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift @@ -420,7 +420,7 @@ public func chatTextLinkEditController(sharedContext: SharedAccountContext, upda controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.inputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller] animated in diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index dc8a1a4308..c2ca5bc861 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -1,9 +1,17 @@ import Foundation import UIKit +#if targetEnvironment(simulator) +@_silgen_name("UIAnimationDragCoefficient") func UIAnimationDragCoefficient() -> Float +#endif + private extension UIView { static var animationDurationFactor: Double { + #if targetEnvironment(simulator) + return Double(UIAnimationDragCoefficient()) + #else return 1.0 + #endif } } @@ -45,7 +53,7 @@ private func makeSpringAnimation(keyPath: String) -> CASpringAnimation { } private extension CALayer { - func makeAnimation(from: AnyObject, to: AnyObject, keyPath: String, duration: Double, delay: Double, curve: Transition.Animation.Curve, removeOnCompletion: Bool, additive: Bool, completion: ((Bool) -> Void)? = nil) -> CAAnimation { + func makeAnimation(from: AnyObject?, to: AnyObject, keyPath: String, duration: Double, delay: Double, curve: Transition.Animation.Curve, removeOnCompletion: Bool, additive: Bool, completion: ((Bool) -> Void)? = nil) -> CAAnimation { switch curve { case .spring: let animation = makeSpringAnimation(keyPath: keyPath) @@ -80,12 +88,14 @@ private extension CALayer { } let animation = CABasicAnimation(keyPath: keyPath) - animation.fromValue = from + if let from = from { + animation.fromValue = from + } animation.toValue = to animation.duration = duration animation.timingFunction = curve.asTimingFunction() animation.isRemovedOnCompletion = removeOnCompletion - animation.fillMode = .forwards + animation.fillMode = .both animation.speed = speed animation.isAdditive = additive if let completion = completion { @@ -112,17 +122,30 @@ private extension Transition.Animation.Curve { switch self { case .easeInOut: return CAMediaTimingFunction(name: .easeInEaseOut) + case let .custom(a, b, c, d): + return CAMediaTimingFunction(controlPoints: a, b, c, d) case .spring: preconditionFailure() } } } +public extension Transition.Animation { + var isImmediate: Bool { + if case .none = self { + return true + } else { + return false + } + } +} + public struct Transition { public enum Animation { public enum Curve { case easeInOut case spring + case custom(Float, Float, Float, Float) } case none @@ -182,14 +205,55 @@ public struct Transition { switch self.animation { case .none: view.frame = frame + //view.bounds = CGRect(origin: view.bounds.origin, size: frame.size) + //view.layer.position = CGPoint(x: frame.midX, y: frame.midY) + view.layer.removeAnimation(forKey: "position") + view.layer.removeAnimation(forKey: "bounds") completion?(true) case .curve: - let previousPosition = view.center - let previousBounds = view.bounds + let previousFrame: CGRect + if (view.layer.animation(forKey: "position") != nil || view.layer.animation(forKey: "bounds") != nil), let presentation = view.layer.presentation() { + previousFrame = presentation.frame + } else { + previousFrame = view.frame + } + view.frame = frame + //view.bounds = CGRect(origin: previousBounds.origin, size: frame.size) + //view.center = CGPoint(x: frame.midX, y: frame.midY) - self.animatePosition(view: view, from: previousPosition, to: view.center, completion: completion) - self.animateBounds(view: view, from: previousBounds, to: view.bounds) + self.animatePosition(view: view, from: CGPoint(x: previousFrame.midX, y: previousFrame.midY), to: CGPoint(x: frame.midX, y: frame.midY), completion: completion) + self.animateBounds(view: view, from: CGRect(origin: view.bounds.origin, size: previousFrame.size), to: CGRect(origin: view.bounds.origin, size: frame.size)) + } + } + + public func setFrame(layer: CALayer, frame: CGRect, completion: ((Bool) -> Void)? = nil) { + if layer.frame == frame { + completion?(true) + return + } + switch self.animation { + case .none: + layer.frame = frame + //view.bounds = CGRect(origin: view.bounds.origin, size: frame.size) + //view.layer.position = CGPoint(x: frame.midX, y: frame.midY) + layer.removeAnimation(forKey: "position") + layer.removeAnimation(forKey: "bounds") + completion?(true) + case .curve: + let previousFrame: CGRect + if (layer.animation(forKey: "position") != nil || layer.animation(forKey: "bounds") != nil), let presentation = layer.presentation() { + previousFrame = presentation.frame + } else { + previousFrame = layer.frame + } + + layer.frame = frame + //view.bounds = CGRect(origin: previousBounds.origin, size: frame.size) + //view.center = CGPoint(x: frame.midX, y: frame.midY) + + self.animatePosition(layer: layer, from: CGPoint(x: previousFrame.midX, y: previousFrame.midY), to: CGPoint(x: frame.midX, y: frame.midY), completion: completion) + self.animateBounds(layer: layer, from: CGRect(origin: layer.bounds.origin, size: previousFrame.size), to: CGRect(origin: layer.bounds.origin, size: frame.size)) } } @@ -201,9 +265,15 @@ public struct Transition { switch self.animation { case .none: view.bounds = bounds + view.layer.removeAnimation(forKey: "bounds") completion?(true) case .curve: - let previousBounds = view.bounds + let previousBounds: CGRect + if view.layer.animation(forKey: "bounds") != nil, let presentation = view.layer.presentation() { + previousBounds = presentation.bounds + } else { + previousBounds = view.layer.bounds + } view.bounds = bounds self.animateBounds(view: view, from: previousBounds, to: view.bounds, completion: completion) @@ -218,15 +288,86 @@ public struct Transition { switch self.animation { case .none: view.center = position + view.layer.removeAnimation(forKey: "position") completion?(true) case .curve: - let previousPosition = view.center + let previousPosition: CGPoint + if view.layer.animation(forKey: "position") != nil, let presentation = view.layer.presentation() { + previousPosition = presentation.position + } else { + previousPosition = view.layer.position + } view.center = position self.animatePosition(view: view, from: previousPosition, to: view.center, completion: completion) } } + public func setBounds(layer: CALayer, bounds: CGRect, completion: ((Bool) -> Void)? = nil) { + if layer.bounds == bounds { + completion?(true) + return + } + switch self.animation { + case .none: + layer.bounds = bounds + layer.removeAnimation(forKey: "bounds") + completion?(true) + case .curve: + let previousBounds: CGRect + if layer.animation(forKey: "bounds") != nil, let presentation = layer.presentation() { + previousBounds = presentation.bounds + } else { + previousBounds = layer.bounds + } + layer.bounds = bounds + + self.animateBounds(layer: layer, from: previousBounds, to: layer.bounds, completion: completion) + } + } + + public func setPosition(layer: CALayer, position: CGPoint, completion: ((Bool) -> Void)? = nil) { + if layer.position == position { + completion?(true) + return + } + switch self.animation { + case .none: + layer.position = position + layer.removeAnimation(forKey: "position") + completion?(true) + case .curve: + let previousPosition: CGPoint + if layer.animation(forKey: "position") != nil, let presentation = layer.presentation() { + previousPosition = presentation.position + } else { + previousPosition = layer.position + } + layer.position = position + + self.animatePosition(layer: layer, from: previousPosition, to: layer.position, completion: completion) + } + } + + public func attachAnimation(view: UIView, completion: @escaping (Bool) -> Void) { + switch self.animation { + case .none: + completion(true) + case let .curve(duration, curve): + view.layer.animate( + from: 0.0 as NSNumber, + to: 1.0 as NSNumber, + keyPath: "attached\(UInt32.random(in: 0 ... UInt32.max))", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: true, + completion: completion + ) + } + } + public func setAlpha(view: UIView, alpha: CGFloat, completion: ((Bool) -> Void)? = nil) { if view.alpha == alpha { completion?(true) @@ -235,9 +376,10 @@ public struct Transition { switch self.animation { case .none: view.alpha = alpha + view.layer.removeAnimation(forKey: "opacity") completion?(true) case .curve: - let previousAlpha = view.alpha + let previousAlpha = (view.layer.presentation()?.opacity).flatMap(CGFloat.init) ?? view.alpha view.alpha = alpha self.animateAlpha(view: view, from: previousAlpha, to: alpha, completion: completion) } @@ -277,12 +419,17 @@ public struct Transition { view.layer.sublayerTransform = transform completion?(true) case let .curve(duration, curve): - let previousValue = view.layer.sublayerTransform + let previousValue: CATransform3D + if let presentation = view.layer.presentation() { + previousValue = presentation.sublayerTransform + } else { + previousValue = view.layer.sublayerTransform + } view.layer.sublayerTransform = transform view.layer.animate( from: NSValue(caTransform3D: previousValue), to: NSValue(caTransform3D: transform), - keyPath: "transform", + keyPath: "sublayerTransform", duration: duration, delay: 0.0, curve: curve, @@ -311,6 +458,25 @@ public struct Transition { ) } } + + public func animateSublayerScale(view: UIView, from fromValue: CGFloat, to toValue: CGFloat, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + switch self.animation { + case .none: + completion?(true) + case let .curve(duration, curve): + view.layer.animate( + from: fromValue as NSNumber, + to: toValue as NSNumber, + keyPath: "sublayerTransform.scale", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: additive, + completion: completion + ) + } + } public func animateAlpha(view: UIView, from fromValue: CGFloat, to toValue: CGFloat, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { switch self.animation { @@ -332,11 +498,23 @@ public struct Transition { } public func animatePosition(view: UIView, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + self.animatePosition(layer: view.layer, from: fromValue, to: toValue, additive: additive, completion: completion) + } + + public func animateBounds(view: UIView, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + self.animateBounds(layer: view.layer, from: fromValue, to: toValue, additive: additive, completion: completion) + } + + public func animateBoundsOrigin(view: UIView, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + self.animateBoundsOrigin(layer: view.layer, from: fromValue, to: toValue, additive: additive, completion: completion) + } + + public func animatePosition(layer: CALayer, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { switch self.animation { case .none: completion?(true) case let .curve(duration, curve): - view.layer.animate( + layer.animate( from: NSValue(cgPoint: fromValue), to: NSValue(cgPoint: toValue), keyPath: "position", @@ -350,12 +528,12 @@ public struct Transition { } } - public func animateBounds(view: UIView, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + public func animateBounds(layer: CALayer, from fromValue: CGRect, to toValue: CGRect, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { switch self.animation { case .none: break case let .curve(duration, curve): - view.layer.animate( + layer.animate( from: NSValue(cgRect: fromValue), to: NSValue(cgRect: toValue), keyPath: "bounds", @@ -368,4 +546,102 @@ public struct Transition { ) } } + + public func animateBoundsOrigin(layer: CALayer, from fromValue: CGPoint, to toValue: CGPoint, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + switch self.animation { + case .none: + break + case let .curve(duration, curve): + layer.animate( + from: NSValue(cgPoint: fromValue), + to: NSValue(cgPoint: toValue), + keyPath: "bounds.origin", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: additive, + completion: completion + ) + } + } + + public func setCornerRadius(layer: CALayer, cornerRadius: CGFloat, completion: ((Bool) -> Void)? = nil) { + if layer.cornerRadius == cornerRadius { + return + } + switch self.animation { + case .none: + layer.cornerRadius = cornerRadius + completion?(true) + case let .curve(duration, curve): + let fromValue: CGFloat + if layer.animation(forKey: "cornerRadius") != nil, let presentation = layer.presentation() { + fromValue = presentation.cornerRadius + } else { + fromValue = layer.cornerRadius + } + layer.cornerRadius = cornerRadius + layer.animate( + from: fromValue as NSNumber, + to: cornerRadius as NSNumber, + keyPath: "cornerRadius", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: false, + completion: completion + ) + } + } + + public func setShapeLayerPath(layer: CAShapeLayer, path: CGPath, completion: ((Bool) -> Void)? = nil) { + switch self.animation { + case .none: + layer.path = path + case let .curve(duration, curve): + if let previousPath = layer.path { + layer.animate( + from: previousPath, + to: path, + keyPath: "path", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: false, + completion: completion + ) + layer.path = path + } else { + layer.path = path + } + } + } + + public func setShapeLayerLineDashPattern(layer: CAShapeLayer, pattern: [NSNumber], completion: ((Bool) -> Void)? = nil) { + switch self.animation { + case .none: + layer.lineDashPattern = pattern + case let .curve(duration, curve): + if let previousLineDashPattern = layer.lineDashPattern { + layer.lineDashPattern = pattern + + layer.animate( + from: previousLineDashPattern as CFArray, + to: pattern as CFArray, + keyPath: "lineDashPattern", + duration: duration, + delay: 0.0, + curve: curve, + removeOnCompletion: true, + additive: false, + completion: completion + ) + } else { + layer.lineDashPattern = pattern + } + } + } } diff --git a/submodules/ComponentFlow/Source/Components/Button.swift b/submodules/ComponentFlow/Source/Components/Button.swift index 078558a048..1332bd0af0 100644 --- a/submodules/ComponentFlow/Source/Components/Button.swift +++ b/submodules/ComponentFlow/Source/Components/Button.swift @@ -7,6 +7,7 @@ public final class Button: Component { public let tag: AnyObject? public let automaticHighlight: Bool public let action: () -> Void + public let holdAction: (() -> Void)? convenience public init( content: AnyComponent, @@ -17,7 +18,8 @@ public final class Button: Component { minSize: nil, tag: nil, automaticHighlight: true, - action: action + action: action, + holdAction: nil ) } @@ -26,13 +28,15 @@ public final class Button: Component { minSize: CGSize? = nil, tag: AnyObject? = nil, automaticHighlight: Bool = true, - action: @escaping () -> Void + action: @escaping () -> Void, + holdAction: (() -> Void)? ) { self.content = content self.minSize = minSize self.tag = tag self.automaticHighlight = automaticHighlight self.action = action + self.holdAction = holdAction } public func minSize(_ minSize: CGSize?) -> Button { @@ -41,7 +45,19 @@ public final class Button: Component { minSize: minSize, tag: self.tag, automaticHighlight: self.automaticHighlight, - action: self.action + action: self.action, + holdAction: self.holdAction + ) + } + + public func withHoldAction(_ holdAction: (() -> Void)?) -> Button { + return Button( + content: self.content, + minSize: self.minSize, + tag: self.tag, + automaticHighlight: self.automaticHighlight, + action: self.action, + holdAction: holdAction ) } @@ -51,7 +67,8 @@ public final class Button: Component { minSize: self.minSize, tag: tag, automaticHighlight: self.automaticHighlight, - action: self.action + action: self.action, + holdAction: self.holdAction ) } @@ -86,6 +103,9 @@ public final class Button: Component { } } + private var holdActionTriggerred: Bool = false + private var holdActionTimer: Timer? + override init(frame: CGRect) { self.contentView = ComponentHostView() self.contentView.isUserInteractionEnabled = false @@ -101,6 +121,10 @@ public final class Button: Component { fatalError("init(coder:) has not been implemented") } + deinit { + self.holdActionTimer?.invalidate() + } + public func matches(tag: Any) -> Bool { if let component = self.component, let componentTag = component.tag { let tag = tag as AnyObject @@ -112,24 +136,69 @@ public final class Button: Component { } @objc private func pressed() { - self.component?.action() + if self.holdActionTriggerred { + self.holdActionTriggerred = false + } else { + self.component?.action() + } } override public func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { self.currentIsHighlighted = true + self.holdActionTriggerred = false + + if self.component?.holdAction != nil { + self.holdActionTriggerred = true + self.component?.action() + + self.holdActionTimer?.invalidate() + if #available(iOS 10.0, *) { + let holdActionTimer = Timer(timeInterval: 0.5, repeats: false, block: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.holdActionTimer?.invalidate() + strongSelf.component?.holdAction?() + strongSelf.beginExecuteHoldActionTimer() + }) + self.holdActionTimer = holdActionTimer + RunLoop.main.add(holdActionTimer, forMode: .common) + } + } + return super.beginTracking(touch, with: event) } + private func beginExecuteHoldActionTimer() { + self.holdActionTimer?.invalidate() + if #available(iOS 10.0, *) { + let holdActionTimer = Timer(timeInterval: 0.1, repeats: true, block: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.component?.holdAction?() + }) + self.holdActionTimer = holdActionTimer + RunLoop.main.add(holdActionTimer, forMode: .common) + } + } + override public func endTracking(_ touch: UITouch?, with event: UIEvent?) { self.currentIsHighlighted = false + self.holdActionTimer?.invalidate() + self.holdActionTimer = nil + super.endTracking(touch, with: event) } override public func cancelTracking(with event: UIEvent?) { self.currentIsHighlighted = false + self.holdActionTimer?.invalidate() + self.holdActionTimer = nil + super.cancelTracking(with: event) } diff --git a/submodules/ComponentFlow/Source/Components/RoundedRectangle.swift b/submodules/ComponentFlow/Source/Components/RoundedRectangle.swift index 3c8153a594..3d1f8a3e1f 100644 --- a/submodules/ComponentFlow/Source/Components/RoundedRectangle.swift +++ b/submodules/ComponentFlow/Source/Components/RoundedRectangle.swift @@ -10,15 +10,17 @@ public final class RoundedRectangle: Component { public let colors: [UIColor] public let cornerRadius: CGFloat public let gradientDirection: GradientDirection + public let stroke: CGFloat? - public convenience init(color: UIColor, cornerRadius: CGFloat) { - self.init(colors: [color], cornerRadius: cornerRadius) + public convenience init(color: UIColor, cornerRadius: CGFloat, stroke: CGFloat? = nil) { + self.init(colors: [color], cornerRadius: cornerRadius, stroke: stroke) } - public init(colors: [UIColor], cornerRadius: CGFloat, gradientDirection: GradientDirection = .horizontal) { + public init(colors: [UIColor], cornerRadius: CGFloat, gradientDirection: GradientDirection = .horizontal, stroke: CGFloat? = nil) { self.colors = colors self.cornerRadius = cornerRadius self.gradientDirection = gradientDirection + self.stroke = stroke } public static func ==(lhs: RoundedRectangle, rhs: RoundedRectangle) -> Bool { @@ -31,6 +33,9 @@ public final class RoundedRectangle: Component { if lhs.gradientDirection != rhs.gradientDirection { return false } + if lhs.stroke != rhs.stroke { + return false + } return true } @@ -40,11 +45,16 @@ public final class RoundedRectangle: Component { func update(component: RoundedRectangle, availableSize: CGSize, transition: Transition) -> CGSize { if self.component != component { if component.colors.count == 1, let color = component.colors.first { - let imageSize = CGSize(width: component.cornerRadius * 2.0, height: component.cornerRadius * 2.0) + let imageSize = CGSize(width: max(component.stroke ?? 0.0, component.cornerRadius) * 2.0, height: max(component.stroke ?? 0.0, component.cornerRadius) * 2.0) UIGraphicsBeginImageContextWithOptions(imageSize, false, 0.0) if let context = UIGraphicsGetCurrentContext() { context.setFillColor(color.cgColor) context.fillEllipse(in: CGRect(origin: CGPoint(), size: imageSize)) + + if let stroke = component.stroke, stroke > 0.0 { + context.setBlendMode(.clear) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: imageSize).insetBy(dx: stroke, dy: stroke)) + } } self.image = UIGraphicsGetImageFromCurrentImageContext()?.stretchableImage(withLeftCapWidth: Int(component.cornerRadius), topCapHeight: Int(component.cornerRadius)) UIGraphicsEndImageContext() @@ -66,6 +76,14 @@ public final class RoundedRectangle: Component { } let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)! context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: component.gradientDirection == .horizontal ? CGPoint(x: imageSize.width, y: 0.0) : CGPoint(x: 0.0, y: imageSize.height), options: CGGradientDrawingOptions()) + + if let stroke = component.stroke, stroke > 0.0 { + context.resetClip() + + context.addPath(UIBezierPath(roundedRect: CGRect(origin: CGPoint(), size: imageSize).insetBy(dx: stroke, dy: stroke), cornerRadius: component.cornerRadius).cgPath) + context.setBlendMode(.clear) + context.fill(CGRect(origin: .zero, size: imageSize)) + } } self.image = UIGraphicsGetImageFromCurrentImageContext()?.stretchableImage(withLeftCapWidth: Int(component.cornerRadius), topCapHeight: Int(component.cornerRadius)) UIGraphicsEndImageContext() diff --git a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift index 3c4698a38e..ec1ae334f0 100644 --- a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift +++ b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift @@ -106,8 +106,24 @@ public final class ComponentHostView: UIView { } override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.alpha.isZero { + return nil + } + if !self.isUserInteractionEnabled { + return nil + } + for view in self.subviews.reversed() { + if view.isUserInteractionEnabled, view.alpha != 0.0, let result = view.hitTest(self.convert(point, to: view), with: event) { + return result + } + } + let result = super.hitTest(point, with: event) - return result + if result != self { + return result + } else { + return nil + } } public func findTaggedView(tag: Any) -> UIView? { @@ -118,3 +134,90 @@ public final class ComponentHostView: UIView { return findTaggedViewImpl(view: componentView, tag: tag) } } + +public final class ComponentView { + private var currentComponent: AnyComponent? + private var currentContainerSize: CGSize? + private var currentSize: CGSize? + public private(set) var view: UIView? + private(set) var isUpdating: Bool = false + + public init() { + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func update(transition: Transition, component: AnyComponent, @EnvironmentBuilder environment: () -> Environment, forceUpdate: Bool = false, containerSize: CGSize) -> CGSize { + let size = self._update(transition: transition, component: component, maybeEnvironment: environment, updateEnvironment: true, forceUpdate: forceUpdate, containerSize: containerSize) + self.currentSize = size + return size + } + + private func _update(transition: Transition, component: AnyComponent, maybeEnvironment: () -> Environment, updateEnvironment: Bool, forceUpdate: Bool, containerSize: CGSize) -> CGSize { + precondition(!self.isUpdating) + self.isUpdating = true + + precondition(containerSize.width.isFinite) + precondition(containerSize.height.isFinite) + + let componentView: UIView + if let current = self.view { + componentView = current + } else { + componentView = component._makeView() + self.view = componentView + } + + let context = componentView.context(component: component) + + let componentState: ComponentState = context.erasedState + + if updateEnvironment { + EnvironmentBuilder._environment = context.erasedEnvironment + let environmentResult = maybeEnvironment() + EnvironmentBuilder._environment = nil + context.erasedEnvironment = environmentResult + } + + let isEnvironmentUpdated = context.erasedEnvironment.calculateIsUpdated() + + + if !forceUpdate, !isEnvironmentUpdated, let currentComponent = self.currentComponent, let currentContainerSize = self.currentContainerSize, let currentSize = self.currentSize { + if currentContainerSize == containerSize && currentComponent == component { + self.isUpdating = false + return currentSize + } + } + self.currentComponent = component + self.currentContainerSize = containerSize + + componentState._updated = { [weak self] transition in + guard let strongSelf = self else { + return + } + let _ = strongSelf._update(transition: transition, component: component, maybeEnvironment: { + preconditionFailure() + } as () -> Environment, updateEnvironment: false, forceUpdate: true, containerSize: containerSize) + } + + let updatedSize = component._update(view: componentView, availableSize: containerSize, environment: context.erasedEnvironment, transition: transition) + + if isEnvironmentUpdated { + context.erasedEnvironment._isUpdated = false + } + + self.isUpdating = false + + return updatedSize + } + + public func findTaggedView(tag: Any) -> UIView? { + guard let view = self.view else { + return nil + } + return findTaggedViewImpl(view: view, tag: tag) + } +} + diff --git a/submodules/ComponentFlow/Source/Utils/ActionSlot.swift b/submodules/ComponentFlow/Source/Utils/ActionSlot.swift index c6dd4aac40..ed351e1dff 100644 --- a/submodules/ComponentFlow/Source/Utils/ActionSlot.swift +++ b/submodules/ComponentFlow/Source/Utils/ActionSlot.swift @@ -15,7 +15,7 @@ public final class Action { public final class ActionSlot: Equatable { private var target: ((Arguments) -> Void)? - init() { + public init() { } public static func ==(lhs: ActionSlot, rhs: ActionSlot) -> Bool { diff --git a/submodules/Components/BlurredBackgroundComponent/BUILD b/submodules/Components/BlurredBackgroundComponent/BUILD new file mode 100644 index 0000000000..5474f19bf9 --- /dev/null +++ b/submodules/Components/BlurredBackgroundComponent/BUILD @@ -0,0 +1,20 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "BlurredBackgroundComponent", + module_name = "BlurredBackgroundComponent", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/Display:Display", + "//submodules/ComponentFlow:ComponentFlow", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift new file mode 100644 index 0000000000..df5f156d2a --- /dev/null +++ b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift @@ -0,0 +1,129 @@ +import Foundation +import UIKit +import ComponentFlow +import Display +import ComponentDisplayAdapters + +public final class BlurredBackgroundComponent: Component { + public let color: UIColor + public let tintContainerView: UIView? + + public init( + color: UIColor, + tintContainerView: UIView? = nil + ) { + self.color = color + self.tintContainerView = tintContainerView + } + + public static func ==(lhs: BlurredBackgroundComponent, rhs: BlurredBackgroundComponent) -> Bool { + if lhs.color != rhs.color { + return false + } + if lhs.tintContainerView !== rhs.tintContainerView { + return false + } + return true + } + + public final class View: BlurredBackgroundView { + private var tintContainerView: UIView? + private var vibrancyEffectView: UIVisualEffectView? + + public func update(component: BlurredBackgroundComponent, availableSize: CGSize, transition: Transition) -> CGSize { + /*if self.tintContainerView !== component.tintContainerView { + if let tintContainerView = self.tintContainerView { + self.tintContainerView = nil + if tintContainerView.superview === self { + tintContainerView.removeFromSuperview() + } + } + + self.tintContainerView = component.tintContainerView + + if let tintContainerView = self.tintContainerView { + let vibrancyEffectView: UIVisualEffectView + if let current = self.vibrancyEffectView { + vibrancyEffectView = current + } else { + let blurEffect = UIBlurEffect(style: .extraLight) + let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) + vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect) + self.vibrancyEffectView = vibrancyEffectView + self.addSubview(vibrancyEffectView) + } + tintContainerView.backgroundColor = .white + vibrancyEffectView.contentView.addSubview(tintContainerView) + } else { + if let vibrancyEffectView = self.vibrancyEffectView { + self.vibrancyEffectView = nil + vibrancyEffectView.removeFromSuperview() + } + } + }*/ + + self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + + /*if let _ = self.viewWithTag(123) { + } else { + let blurEffect = UIBlurEffect(style: .extraLight) + + + /*let segmentedControl = UISegmentedControl(items: ["First Item", "Second Item"]) + segmentedControl.sizeToFit() + segmentedControl.center = CGPoint(x: 250.0, y: 250.0)*/ + let testView = UIView(frame: CGRect(origin: CGPoint(x: 50.0, y: 100.0), size: CGSize(width: 250.0, height: 50.0))) + testView.backgroundColor = .white + + let testView2 = UILabel() + testView2.text = "Test 13245" + testView2.font = Font.semibold(17.0) + testView2.textColor = .black + testView2.sizeToFit() + + testView2.center = CGPoint(x: 250.0 - testView.frame.minX, y: 490.0 - testView.frame.minY) + + let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) + let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect) + //vibrancyEffectView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 400.0, height: 300.0)) + vibrancyEffectView.tag = 123 + + vibrancyEffectView.contentView.addSubview(testView) + testView.addSubview(testView2) + //vibrancyEffectView.contentView.addSubview(testView2) + + self.addSubview(vibrancyEffectView) + + /*let view = UIView() + view.tag = 123 + view.layer.compositingFilter = "sourceOverCompositing" + view.backgroundColor = .white + view.frame = CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 200.0)) + self.addSubview(view)*/ + } + + if let view = self.viewWithTag(123) { + view.frame = CGRect(origin: CGPoint(), size: availableSize) + }*/ + + self.update(size: availableSize, transition: transition.containedViewLayoutTransition) + + if let tintContainerView = self.tintContainerView { + transition.setFrame(view: tintContainerView, frame: CGRect(origin: CGPoint(), size: availableSize)) + } + if let vibrancyEffectView = self.vibrancyEffectView { + transition.setFrame(view: vibrancyEffectView, frame: CGRect(origin: CGPoint(), size: availableSize)) + } + + return availableSize + } + } + + public func makeView() -> View { + return View(color: nil, enableBlur: true) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} diff --git a/submodules/Components/BundleIconComponent/Sources/BundleIconComponent.swift b/submodules/Components/BundleIconComponent/Sources/BundleIconComponent.swift index fb3955c404..e055375462 100644 --- a/submodules/Components/BundleIconComponent/Sources/BundleIconComponent.swift +++ b/submodules/Components/BundleIconComponent/Sources/BundleIconComponent.swift @@ -7,10 +7,12 @@ import Display public final class BundleIconComponent: Component { public let name: String public let tintColor: UIColor? + public let maxSize: CGSize? - public init(name: String, tintColor: UIColor?) { + public init(name: String, tintColor: UIColor?, maxSize: CGSize? = nil) { self.name = name self.tintColor = tintColor + self.maxSize = maxSize } public static func ==(lhs: BundleIconComponent, rhs: BundleIconComponent) -> Bool { @@ -20,6 +22,9 @@ public final class BundleIconComponent: Component { if lhs.tintColor != rhs.tintColor { return false } + if lhs.maxSize != rhs.maxSize { + return false + } return true } @@ -44,7 +49,10 @@ public final class BundleIconComponent: Component { } self.component = component - let imageSize = self.image?.size ?? CGSize() + var imageSize = self.image?.size ?? CGSize() + if let maxSize = component.maxSize { + imageSize = imageSize.aspectFitted(maxSize) + } return CGSize(width: min(imageSize.width, availableSize.width), height: min(imageSize.height, availableSize.height)) } diff --git a/submodules/Components/ComponentDisplayAdapters/BUILD b/submodules/Components/ComponentDisplayAdapters/BUILD new file mode 100644 index 0000000000..50101fc7ad --- /dev/null +++ b/submodules/Components/ComponentDisplayAdapters/BUILD @@ -0,0 +1,19 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ComponentDisplayAdapters", + module_name = "ComponentDisplayAdapters", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/Display:Display", + "//submodules/ComponentFlow:ComponentFlow", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift b/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift new file mode 100644 index 0000000000..2c50f91083 --- /dev/null +++ b/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift @@ -0,0 +1,52 @@ +import Foundation +import UIKit +import ComponentFlow +import Display + +public extension Transition.Animation.Curve { + init(_ curve: ContainedViewLayoutTransitionCurve) { + switch curve { + case .linear: + self = .easeInOut + case .easeInOut: + self = .easeInOut + case let .custom(a, b, c, d): + self = .custom(a, b, c, d) + case .customSpring: + self = .spring + case .spring: + self = .spring + } + } + + var containedViewLayoutTransitionCurve: ContainedViewLayoutTransitionCurve { + switch self { + case .easeInOut: + return .easeInOut + case .spring: + return .spring + case let .custom(a, b, c, d): + return .custom(a, b, c, d) + } + } +} + +public extension Transition { + init(_ transition: ContainedViewLayoutTransition) { + switch transition { + case .immediate: + self.init(animation: .none) + case let .animated(duration, curve): + self.init(animation: .curve(duration: duration, curve: Transition.Animation.Curve(curve))) + } + } + + var containedViewLayoutTransition: ContainedViewLayoutTransition { + switch self.animation { + case .none: + return .immediate + case let .curve(duration, curve): + return .animated(duration: duration, curve: curve.containedViewLayoutTransitionCurve) + } + } +} diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index c3887fa3ac..c584daf0e8 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -7,29 +7,34 @@ import Display public final class LottieAnimationComponent: Component { public struct AnimationItem: Equatable { + public enum StillPosition { + case begin + case end + } + public enum Mode: Equatable { - case still + case still(position: StillPosition) case animating(loop: Bool) case animateTransitionFromPrevious } public var name: String public var mode: Mode - public var colors: [String: UIColor] - public init(name: String, colors: [String: UIColor], mode: Mode) { + public init(name: String, mode: Mode) { self.name = name - self.colors = colors self.mode = mode } } public let animation: AnimationItem + public let colors: [String: UIColor] public let tag: AnyObject? public let size: CGSize? - public init(animation: AnimationItem, tag: AnyObject? = nil, size: CGSize?) { + public init(animation: AnimationItem, colors: [String: UIColor], tag: AnyObject? = nil, size: CGSize?) { self.animation = animation + self.colors = colors self.tag = tag self.size = size } @@ -37,6 +42,7 @@ public final class LottieAnimationComponent: Component { public func tagged(_ tag: AnyObject?) -> LottieAnimationComponent { return LottieAnimationComponent( animation: self.animation, + colors: self.colors, tag: tag, size: self.size ) @@ -46,6 +52,9 @@ public final class LottieAnimationComponent: Component { if lhs.animation != rhs.animation { return false } + if lhs.colors != rhs.colors { + return false + } if lhs.tag !== rhs.tag { return false } @@ -112,10 +121,19 @@ public final class LottieAnimationComponent: Component { func update(component: LottieAnimationComponent, availableSize: CGSize, transition: Transition) -> CGSize { var updatePlayback = false + var updateColors = false + + if let currentComponent = self.component, currentComponent.colors != component.colors { + updateColors = true + } + + var animateSize = true + var updateComponent = true if self.component?.animation != component.animation { if let animationView = self.animationView { if case .animateTransitionFromPrevious = component.animation.mode, !animationView.isAnimationPlaying, !self.didPlayToCompletion { + updateComponent = false animationView.play { [weak self] _ in self?.currentCompletion?() } @@ -123,6 +141,7 @@ public final class LottieAnimationComponent: Component { } if let animationView = self.animationView, animationView.isAnimationPlaying { + updateComponent = false self.currentCompletion = { [weak self] in guard let strongSelf = self else { return @@ -136,6 +155,7 @@ public final class LottieAnimationComponent: Component { self.animationView?.removeFromSuperview() self.didPlayToCompletion = false + self.currentCompletion = nil if let url = getAppBundle().url(forResource: component.animation.name, withExtension: "json"), let animation = Animation.filepath(url.path) { let view = AnimationView(animation: animation, configuration: LottieConfiguration(renderingEngine: .mainThread, decodingStrategy: .codable)) @@ -153,23 +173,36 @@ public final class LottieAnimationComponent: Component { view.backgroundColor = .clear view.isOpaque = false - //view.logHierarchyKeypaths() - - for (key, value) in component.animation.colors { - view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) - /*let colorCallback = LOTColorValueCallback(color: value.cgColor) - self.colorCallbacks.append(colorCallback) - view.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/ - } + updateColors = true self.animationView = view self.addSubview(view) + animateSize = false updatePlayback = true } } } + if updateComponent { + self.component = component + } + + if updateColors, let animationView = self.animationView { + if let value = component.colors["__allcolors__"] { + for keypath in animationView.allKeypaths(predicate: { $0.keys.last == "Color" }) { + animationView.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: keypath)) + } + } + + for (key, value) in component.colors { + if key == "__allcolors__" { + continue + } + animationView.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) + } + } + var animationSize = CGSize() if let animationView = self.animationView, let animation = animationView.animation { animationSize = animation.size @@ -181,7 +214,36 @@ public final class LottieAnimationComponent: Component { let size = CGSize(width: min(animationSize.width, availableSize.width), height: min(animationSize.height, availableSize.height)) if let animationView = self.animationView { - animationView.frame = CGRect(origin: CGPoint(x: floor((size.width - animationSize.width) / 2.0), y: floor((size.height - animationSize.height) / 2.0)), size: animationSize) + let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - animationSize.width) / 2.0), y: floor((size.height - animationSize.height) / 2.0)), size: animationSize) + + if animationView.frame != animationFrame { + if !transition.animation.isImmediate && animateSize && !animationView.frame.isEmpty && animationView.frame.size != animationFrame.size { + let previouosAnimationFrame = animationView.frame + + if let snapshotView = animationView.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = previouosAnimationFrame + + animationView.superview?.insertSubview(snapshotView, belowSubview: animationView) + + transition.setPosition(view: snapshotView, position: CGPoint(x: animationFrame.midX, y: animationFrame.midY)) + snapshotView.bounds = CGRect(origin: CGPoint(), size: animationFrame.size) + let scaleFactor = previouosAnimationFrame.width / animationFrame.width + transition.animateScale(view: snapshotView, from: scaleFactor, to: 1.0) + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } + + transition.setPosition(view: animationView, position: CGPoint(x: animationFrame.midX, y: animationFrame.midY)) + transition.setBounds(view: animationView, bounds: CGRect(origin: CGPoint(), size: animationFrame.size)) + transition.animateSublayerScale(view: animationView, from: previouosAnimationFrame.width / animationFrame.width, to: 1.0) + animationView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) + } else if animationView.frame.size == animationFrame.size { + transition.setFrame(view: animationView, frame: animationFrame) + } else { + animationView.frame = animationFrame + } + } if updatePlayback { if case .animating = component.animation.mode { @@ -191,6 +253,14 @@ public final class LottieAnimationComponent: Component { } } } else { + if case let .still(position) = component.animation.mode { + switch position { + case .begin: + animationView.currentFrame = 0.0 + case .end: + animationView.currentFrame = animationView.animation?.endFrame ?? 0.0 + } + } if animationView.isAnimationPlaying { animationView.stop() } diff --git a/submodules/TelegramUI/Components/EmojiKeyboard/BUILD b/submodules/Components/PagerComponent/BUILD similarity index 72% rename from submodules/TelegramUI/Components/EmojiKeyboard/BUILD rename to submodules/Components/PagerComponent/BUILD index 525cbd2996..ed1b87f808 100644 --- a/submodules/TelegramUI/Components/EmojiKeyboard/BUILD +++ b/submodules/Components/PagerComponent/BUILD @@ -1,8 +1,8 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") swift_library( - name = "EmojiKeyboard", - module_name = "EmojiKeyboard", + name = "PagerComponent", + module_name = "PagerComponent", srcs = glob([ "Sources/**/*.swift", ]), @@ -11,6 +11,7 @@ swift_library( ], deps = [ "//submodules/Display:Display", + "//submodules/ComponentFlow:ComponentFlow", ], visibility = [ "//visibility:public", diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift new file mode 100644 index 0000000000..f5d31dfa3a --- /dev/null +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -0,0 +1,838 @@ +import Foundation +import UIKit +import Display +import ComponentFlow + +public protocol PagerExpandableScrollView: UIScrollView { +} + +public protocol PagerPanGestureRecognizer: UIGestureRecognizer { +} + +open class PagerExternalTopPanelContainer: SparseContainerView { +} + +public protocol PagerContentViewWithBackground: UIView { + func pagerUpdateBackground(backgroundFrame: CGRect, transition: Transition) +} + +public final class PagerComponentChildEnvironment: Equatable { + public struct ContentScrollingUpdate { + public var relativeOffset: CGFloat + public var absoluteOffsetToTopEdge: CGFloat? + public var absoluteOffsetToBottomEdge: CGFloat? + public var isReset: Bool + public var isInteracting: Bool + public var transition: Transition + + public init( + relativeOffset: CGFloat, + absoluteOffsetToTopEdge: CGFloat?, + absoluteOffsetToBottomEdge: CGFloat?, + isReset: Bool, + isInteracting: Bool, + transition: Transition + ) { + self.relativeOffset = relativeOffset + self.absoluteOffsetToTopEdge = absoluteOffsetToTopEdge + self.absoluteOffsetToBottomEdge = absoluteOffsetToBottomEdge + self.isReset = isReset + self.isInteracting = isInteracting + self.transition = transition + } + } + + public let containerInsets: UIEdgeInsets + public let onChildScrollingUpdate: (ContentScrollingUpdate) -> Void + + init( + containerInsets: UIEdgeInsets, + onChildScrollingUpdate: @escaping (ContentScrollingUpdate) -> Void + ) { + self.containerInsets = containerInsets + self.onChildScrollingUpdate = onChildScrollingUpdate + } + + public static func ==(lhs: PagerComponentChildEnvironment, rhs: PagerComponentChildEnvironment) -> Bool { + if lhs.containerInsets != rhs.containerInsets { + return false + } + + return true + } +} + +public final class PagerComponentPanelEnvironment: Equatable { + public let contentOffset: CGFloat + public let contentTopPanels: [AnyComponentWithIdentity] + public let contentIcons: [PagerComponentContentIcon] + public let contentAccessoryLeftButtons: [AnyComponentWithIdentity] + public let contentAccessoryRightButtons: [AnyComponentWithIdentity] + public let activeContentId: AnyHashable? + public let navigateToContentId: (AnyHashable) -> Void + public let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + public let isExpandedUpdated: (Bool, Transition) -> Void + + init( + contentOffset: CGFloat, + contentTopPanels: [AnyComponentWithIdentity], + contentIcons: [PagerComponentContentIcon], + contentAccessoryLeftButtons: [AnyComponentWithIdentity], + contentAccessoryRightButtons: [AnyComponentWithIdentity], + activeContentId: AnyHashable?, + navigateToContentId: @escaping (AnyHashable) -> Void, + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, + isExpandedUpdated: @escaping (Bool, Transition) -> Void + ) { + self.contentOffset = contentOffset + self.contentTopPanels = contentTopPanels + self.contentIcons = contentIcons + self.contentAccessoryLeftButtons = contentAccessoryLeftButtons + self.contentAccessoryRightButtons = contentAccessoryRightButtons + self.activeContentId = activeContentId + self.navigateToContentId = navigateToContentId + self.visibilityFractionUpdated = visibilityFractionUpdated + self.isExpandedUpdated = isExpandedUpdated + } + + public static func ==(lhs: PagerComponentPanelEnvironment, rhs: PagerComponentPanelEnvironment) -> Bool { + if lhs.contentOffset != rhs.contentOffset { + return false + } + if lhs.contentTopPanels != rhs.contentTopPanels { + return false + } + if lhs.contentIcons != rhs.contentIcons { + return false + } + if lhs.contentAccessoryLeftButtons != rhs.contentAccessoryLeftButtons { + return false + } + if lhs.contentAccessoryRightButtons != rhs.contentAccessoryRightButtons { + return false + } + if lhs.activeContentId != rhs.activeContentId { + return false + } + if lhs.visibilityFractionUpdated !== rhs.visibilityFractionUpdated { + return false + } + + return true + } +} + +public struct PagerComponentPanelState { + public var topPanelHeight: CGFloat + + public init(topPanelHeight: CGFloat) { + self.topPanelHeight = topPanelHeight + } +} + +public final class PagerComponentViewTag { + public init() { + } +} + +public enum PagerComponentPanelHideBehavior { + case hideOnScroll + case show + case hide +} + +public final class PagerComponentContentIcon: Equatable { + public let id: AnyHashable + public let imageName: String + + public init(id: AnyHashable, imageName: String) { + self.id = id + self.imageName = imageName + } + + public static func ==(lhs: PagerComponentContentIcon, rhs: PagerComponentContentIcon) -> Bool { + if lhs === rhs { + return true + } + if lhs.id != rhs.id { + return false + } + if lhs.imageName != rhs.imageName { + return false + } + return true + } +} + +public final class PagerComponent: Component { + public typealias EnvironmentType = ChildEnvironmentType + + public let contentInsets: UIEdgeInsets + public let contents: [AnyComponentWithIdentity<(ChildEnvironmentType, PagerComponentChildEnvironment)>] + public let contentTopPanels: [AnyComponentWithIdentity] + public let contentIcons: [PagerComponentContentIcon] + public let contentAccessoryLeftButtons:[AnyComponentWithIdentity] + public let contentAccessoryRightButtons:[AnyComponentWithIdentity] + public let defaultId: AnyHashable? + public let contentBackground: AnyComponent? + public let topPanel: AnyComponent>? + public let externalTopPanelContainer: PagerExternalTopPanelContainer? + public let bottomPanel: AnyComponent>? + public let panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? + public let isTopPanelExpandedUpdated: (Bool, Transition) -> Void + public let panelHideBehavior: PagerComponentPanelHideBehavior + + public init( + contentInsets: UIEdgeInsets, + contents: [AnyComponentWithIdentity<(ChildEnvironmentType, PagerComponentChildEnvironment)>], + contentTopPanels: [AnyComponentWithIdentity], + contentIcons: [PagerComponentContentIcon], + contentAccessoryLeftButtons: [AnyComponentWithIdentity], + contentAccessoryRightButtons: [AnyComponentWithIdentity], + defaultId: AnyHashable?, + contentBackground: AnyComponent?, + topPanel: AnyComponent>?, + externalTopPanelContainer: PagerExternalTopPanelContainer?, + bottomPanel: AnyComponent>?, + panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)?, + isTopPanelExpandedUpdated: @escaping (Bool, Transition) -> Void, + panelHideBehavior: PagerComponentPanelHideBehavior + ) { + self.contentInsets = contentInsets + self.contents = contents + self.contentTopPanels = contentTopPanels + self.contentIcons = contentIcons + self.contentAccessoryLeftButtons = contentAccessoryLeftButtons + self.contentAccessoryRightButtons = contentAccessoryRightButtons + self.defaultId = defaultId + self.contentBackground = contentBackground + self.topPanel = topPanel + self.externalTopPanelContainer = externalTopPanelContainer + self.bottomPanel = bottomPanel + self.panelStateUpdated = panelStateUpdated + self.isTopPanelExpandedUpdated = isTopPanelExpandedUpdated + self.panelHideBehavior = panelHideBehavior + } + + public static func ==(lhs: PagerComponent, rhs: PagerComponent) -> Bool { + if lhs.contentInsets != rhs.contentInsets { + return false + } + if lhs.contents != rhs.contents { + return false + } + if lhs.contentTopPanels != rhs.contentTopPanels { + return false + } + if lhs.contentIcons != rhs.contentIcons { + return false + } + if lhs.defaultId != rhs.defaultId { + return false + } + if lhs.contentBackground != rhs.contentBackground { + return false + } + if lhs.topPanel != rhs.topPanel { + return false + } + if lhs.externalTopPanelContainer !== rhs.externalTopPanelContainer { + return false + } + if lhs.bottomPanel != rhs.bottomPanel { + return false + } + if lhs.panelHideBehavior != rhs.panelHideBehavior { + return false + } + + return true + } + + public final class View: UIView, ComponentTaggedView { + private final class ContentView { + let view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)> + var scrollingPanelOffsetToTopEdge: CGFloat = 0.0 + var scrollingPanelOffsetToBottomEdge: CGFloat = .greatestFiniteMagnitude + var scrollingPanelOffsetFraction: CGFloat = 0.0 + + init(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>) { + self.view = view + } + } + + private final class PagerPanGestureRecognizerImpl: UIPanGestureRecognizer, PagerPanGestureRecognizer { + } + + private struct PaneTransitionGestureState { + var fraction: CGFloat = 0.0 + } + + private var contentViews: [AnyHashable: ContentView] = [:] + private var contentBackgroundView: ComponentHostView? + private let topPanelVisibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + private var topPanelView: ComponentHostView>? + private let bottomPanelVisibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + private var bottomPanelView: ComponentHostView>? + + private var topPanelHeight: CGFloat? + private var bottomPanelHeight: CGFloat? + + public private(set) var centralId: AnyHashable? + private var paneTransitionGestureState: PaneTransitionGestureState? + + private var component: PagerComponent? + private weak var state: EmptyComponentState? + + private var panRecognizer: PagerPanGestureRecognizerImpl? + + private var isTopPanelExpanded: Bool = false + + public var topPanelComponentView: UIView? { + return self.topPanelView?.componentView + } + + override init(frame: CGRect) { + super.init(frame: frame) + + self.disablesInteractiveTransitionGestureRecognizer = true + + let panRecognizer = PagerPanGestureRecognizerImpl(target: self, action: #selector(self.panGesture(_:))) + self.panRecognizer = panRecognizer + self.addGestureRecognizer(panRecognizer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func matches(tag: Any) -> Bool { + if tag is PagerComponentViewTag { + return true + } + + return false + } + + @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { + switch recognizer.state { + case .began: + self.paneTransitionGestureState = PaneTransitionGestureState() + case .changed: + if let centralId = self.centralId, let component = self.component, let centralIndex = component.contents.firstIndex(where: { $0.id == centralId }), var paneTransitionGestureState = self.paneTransitionGestureState, self.bounds.width > 0.0 { + var fraction = recognizer.translation(in: self).x / self.bounds.width + if centralIndex <= 0 { + fraction = min(0.0, fraction) + } + if centralIndex >= component.contents.count - 1 { + fraction = max(0.0, fraction) + } + paneTransitionGestureState.fraction = fraction + + self.paneTransitionGestureState = paneTransitionGestureState + self.state?.updated(transition: .immediate) + } + case .ended, .cancelled: + if let paneTransitionGestureState = self.paneTransitionGestureState { + self.paneTransitionGestureState = nil + + var updateTopPanelExpanded = false + + if paneTransitionGestureState.fraction != 0.0, let component = self.component, let centralId = self.centralId, let centralIndex = component.contents.firstIndex(where: { $0.id == centralId }) { + let fraction = recognizer.translation(in: self).x / self.bounds.width + let velocity = recognizer.velocity(in: self) + + var updatedCentralIndex = centralIndex + if abs(velocity.x) > 180.0 { + if velocity.x > 0.0 { + updatedCentralIndex = max(0, updatedCentralIndex - 1) + } else { + updatedCentralIndex = min(component.contents.count - 1, updatedCentralIndex + 1) + } + } else if abs(fraction) > 0.35 { + if fraction > 0.0 { + updatedCentralIndex = max(0, updatedCentralIndex - 1) + } else { + updatedCentralIndex = min(component.contents.count - 1, updatedCentralIndex + 1) + } + } + if updatedCentralIndex != centralIndex { + self.centralId = component.contents[updatedCentralIndex].id + + if self.isTopPanelExpanded { + updateTopPanelExpanded = true + } + } + } + + if updateTopPanelExpanded { + self.isTopPanelExpandedUpdated(isExpanded: false, transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + } else { + self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + } + } + default: + break + } + } + + func update(component: PagerComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let previousPanelHideBehavior = self.component?.panelHideBehavior + + var panelStateTransition = transition + if let previousPanelHideBehavior = previousPanelHideBehavior, previousPanelHideBehavior != component.panelHideBehavior, panelStateTransition.animation.isImmediate { + panelStateTransition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + } + + self.component = component + self.state = state + + let navigateToContentId: (AnyHashable) -> Void = { [weak self] id in + guard let strongSelf = self else { + return + } + + var updateTopPanelExpanded = false + if strongSelf.centralId != id { + strongSelf.centralId = id + + if strongSelf.isTopPanelExpanded { + updateTopPanelExpanded = true + } + } + + if updateTopPanelExpanded { + strongSelf.isTopPanelExpandedUpdated(isExpanded: false, transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + } else { + strongSelf.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + } + } + + var centralId: AnyHashable? + if let current = self.centralId { + if component.contents.contains(where: { $0.id == current }) { + centralId = current + } + } + if centralId == nil { + if let defaultId = component.defaultId { + if component.contents.contains(where: { $0.id == defaultId }) { + centralId = defaultId + } + } + if centralId == nil { + centralId = component.contents.first?.id + } + } + + if self.centralId != centralId { + self.centralId = centralId + } + + var contentInsets = component.contentInsets + contentInsets.bottom = 0.0 + + var scrollingPanelOffsetFraction: CGFloat + if case .show = component.panelHideBehavior { + scrollingPanelOffsetFraction = 0.0 + } else if let centralId = centralId, let centralContentView = self.contentViews[centralId] { + scrollingPanelOffsetFraction = centralContentView.scrollingPanelOffsetFraction + } else { + scrollingPanelOffsetFraction = 0.0 + } + + var topPanelHeight: CGFloat = 0.0 + if let topPanel = component.topPanel { + let topPanelView: ComponentHostView> + var topPanelTransition = panelStateTransition + if let current = self.topPanelView { + topPanelView = current + } else { + topPanelTransition = .immediate + topPanelView = ComponentHostView>() + self.topPanelView = topPanelView + } + + let topPanelSuperview = component.externalTopPanelContainer ?? self + if topPanelView.superview !== topPanelSuperview { + topPanelSuperview.addSubview(topPanelView) + } + + let topPanelSize = topPanelView.update( + transition: topPanelTransition, + component: topPanel, + environment: { + PagerComponentPanelEnvironment( + contentOffset: 0.0, + contentTopPanels: component.contentTopPanels, + contentIcons: [], + contentAccessoryLeftButtons: [], + contentAccessoryRightButtons: [], + activeContentId: centralId, + navigateToContentId: navigateToContentId, + visibilityFractionUpdated: self.topPanelVisibilityFractionUpdated, + isExpandedUpdated: { [weak self] isExpanded, transition in + guard let strongSelf = self else { + return + } + strongSelf.isTopPanelExpandedUpdated(isExpanded: isExpanded, transition: transition) + } + ) + }, + containerSize: availableSize + ) + + self.topPanelHeight = topPanelSize.height + + var topPanelOffset = topPanelSize.height * scrollingPanelOffsetFraction + + var topPanelVisibilityFraction: CGFloat = 1.0 - scrollingPanelOffsetFraction + switch component.panelHideBehavior { + case .hide: + topPanelVisibilityFraction = 0.0 + case .show: + topPanelVisibilityFraction = 1.0 + case .hideOnScroll: + break + } + + self.topPanelVisibilityFractionUpdated.invoke((topPanelVisibilityFraction, topPanelTransition)) + + topPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + + if case .hide = component.panelHideBehavior { + topPanelOffset = topPanelSize.height + } + + if component.externalTopPanelContainer != nil { + var visibleTopPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + if case .hide = component.panelHideBehavior { + visibleTopPanelHeight = 0.0 + } + panelStateTransition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(), size: CGSize(width: topPanelSize.width, height: visibleTopPanelHeight))) + } else { + panelStateTransition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topPanelOffset), size: topPanelSize)) + } + + contentInsets.top += topPanelSize.height + } else { + if let topPanelView = self.topPanelView { + self.topPanelView = nil + + topPanelView.removeFromSuperview() + } + + self.topPanelHeight = 0.0 + } + + var bottomPanelOffset: CGFloat = 0.0 + if let bottomPanel = component.bottomPanel { + let bottomPanelView: ComponentHostView> + var bottomPanelTransition = panelStateTransition + if let current = self.bottomPanelView { + bottomPanelView = current + } else { + bottomPanelTransition = .immediate + bottomPanelView = ComponentHostView>() + self.bottomPanelView = bottomPanelView + self.addSubview(bottomPanelView) + } + let bottomPanelSize = bottomPanelView.update( + transition: bottomPanelTransition, + component: bottomPanel, + environment: { + PagerComponentPanelEnvironment( + contentOffset: 0.0, + contentTopPanels: [], + contentIcons: component.contentIcons, + contentAccessoryLeftButtons: component.contentAccessoryLeftButtons, + contentAccessoryRightButtons: component.contentAccessoryRightButtons, + activeContentId: centralId, + navigateToContentId: navigateToContentId, + visibilityFractionUpdated: self.bottomPanelVisibilityFractionUpdated, + isExpandedUpdated: { _, _ in + } + ) + }, + containerSize: availableSize + ) + + self.bottomPanelHeight = bottomPanelSize.height + + bottomPanelOffset = bottomPanelSize.height * scrollingPanelOffsetFraction + if case .hide = component.panelHideBehavior { + bottomPanelOffset = bottomPanelSize.height + } + + panelStateTransition.setFrame(view: bottomPanelView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - bottomPanelSize.height + bottomPanelOffset), size: bottomPanelSize)) + + contentInsets.bottom += bottomPanelSize.height + } else { + if let bottomPanelView = self.bottomPanelView { + self.bottomPanelView = nil + + bottomPanelView.removeFromSuperview() + } + + self.bottomPanelHeight = 0.0 + } + + let effectiveTopPanelHeight: CGFloat + switch component.panelHideBehavior { + case .hide: + effectiveTopPanelHeight = 0.0 + case .show, .hideOnScroll: + if component.externalTopPanelContainer != nil { + effectiveTopPanelHeight = topPanelHeight + } else { + effectiveTopPanelHeight = 0.0 + } + } + + let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: effectiveTopPanelHeight), size: CGSize(width: availableSize.width, height: availableSize.height - effectiveTopPanelHeight + bottomPanelOffset)) + if let contentBackground = component.contentBackground { + let contentBackgroundView: ComponentHostView + var contentBackgroundTransition = panelStateTransition + if let current = self.contentBackgroundView { + contentBackgroundView = current + } else { + contentBackgroundTransition = .immediate + contentBackgroundView = ComponentHostView() + self.contentBackgroundView = contentBackgroundView + self.insertSubview(contentBackgroundView, at: 0) + } + let _ = contentBackgroundView.update( + transition: contentBackgroundTransition, + component: contentBackground, + environment: {}, + containerSize: backgroundFrame.size + ) + contentBackgroundTransition.setFrame(view: contentBackgroundView, frame: backgroundFrame) + } else { + if let contentBackgroundView = self.contentBackgroundView { + self.contentBackgroundView = nil + contentBackgroundView.removeFromSuperview() + } + } + + var validIds: [AnyHashable] = [] + if let centralId = self.centralId, let centralIndex = component.contents.firstIndex(where: { $0.id == centralId }) { + let contentSize = CGSize(width: availableSize.width, height: availableSize.height) + + var referenceFrames: [AnyHashable: CGRect] = [:] + if case .none = transition.animation { + } else { + for (id, contentView) in self.contentViews { + referenceFrames[id] = contentView.view.frame + } + } + + for index in 0 ..< component.contents.count { + let indexOffset = index - centralIndex + let clippedIndexOffset = max(-1, min(1, indexOffset)) + var checkingContentFrame = CGRect(origin: CGPoint(x: contentSize.width * CGFloat(indexOffset), y: 0.0), size: contentSize) + var contentFrame = CGRect(origin: CGPoint(x: contentSize.width * CGFloat(clippedIndexOffset), y: 0.0), size: contentSize) + + if let paneTransitionGestureState = self.paneTransitionGestureState { + checkingContentFrame.origin.x += paneTransitionGestureState.fraction * availableSize.width + contentFrame.origin.x += paneTransitionGestureState.fraction * availableSize.width + } + let content = component.contents[index] + + let isInBounds = CGRect(origin: CGPoint(), size: availableSize).intersects(checkingContentFrame) + + var isPartOfTransition = false + if case .none = transition.animation { + } else if self.contentViews[content.id] != nil { + isPartOfTransition = true + } + + if isInBounds || isPartOfTransition || content.id == centralId { + let id = content.id + validIds.append(content.id) + + var wasAdded = false + var contentTransition = transition + let contentView: ContentView + if let current = self.contentViews[content.id] { + contentView = current + } else { + wasAdded = true + contentView = ContentView(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>()) + contentTransition = .immediate + self.contentViews[content.id] = contentView + if let contentBackgroundView = self.contentBackgroundView { + self.insertSubview(contentView.view, aboveSubview: contentBackgroundView) + } else { + self.insertSubview(contentView.view, at: 0) + } + } + + let pagerChildEnvironment = PagerComponentChildEnvironment( + containerInsets: contentInsets, + onChildScrollingUpdate: { [weak self] update in + guard let strongSelf = self else { + return + } + strongSelf.onChildScrollingUpdate(id: id, update: update) + } + ) + + let _ = contentView.view.update( + transition: contentTransition, + component: content.component, + environment: { + environment[ChildEnvironmentType.self] + pagerChildEnvironment + }, + containerSize: contentFrame.size + ) + + if wasAdded { + if case .none = transition.animation { + contentView.view.frame = contentFrame + } else { + var referenceDirectionIsRight: Bool? + for (previousId, previousFrame) in referenceFrames { + if let previousIndex = component.contents.firstIndex(where: { $0.id == previousId }) { + if previousFrame.minX == 0.0 { + if previousIndex < index { + referenceDirectionIsRight = true + } else { + referenceDirectionIsRight = false + } + break + } + } + } + if let referenceDirectionIsRight = referenceDirectionIsRight { + contentView.view.frame = contentFrame.offsetBy(dx: referenceDirectionIsRight ? contentFrame.width : (-contentFrame.width), dy: 0.0) + transition.setFrame(view: contentView.view, frame: contentFrame, completion: { [weak self] completed in + if completed && !isInBounds && isPartOfTransition { + DispatchQueue.main.async { + self?.state?.updated(transition: .immediate) + } + } + }) + } else { + contentView.view.frame = contentFrame + } + } + } else { + transition.setFrame(view: contentView.view, frame: contentFrame, completion: { [weak self] completed in + if completed && !isInBounds && isPartOfTransition { + DispatchQueue.main.async { + self?.state?.updated(transition: .immediate) + } + } + }) + } + + if let contentViewWithBackground = contentView.view.componentView as? PagerContentViewWithBackground { + contentViewWithBackground.pagerUpdateBackground(backgroundFrame: backgroundFrame, transition: contentTransition) + } + } + } + } + + var removedIds: [AnyHashable] = [] + for (id, _) in self.contentViews { + if !validIds.contains(id) { + removedIds.append(id) + } + } + for id in removedIds { + self.contentViews.removeValue(forKey: id)?.view.removeFromSuperview() + } + + if let panelStateUpdated = component.panelStateUpdated { + panelStateUpdated( + PagerComponentPanelState( + topPanelHeight: topPanelHeight + ), + panelStateTransition + ) + } + + return availableSize + } + + private func onChildScrollingUpdate(id: AnyHashable, update: PagerComponentChildEnvironment.ContentScrollingUpdate) { + guard let contentView = self.contentViews[id] else { + return + } + + var offsetDelta: CGFloat? + offsetDelta = (update.absoluteOffsetToTopEdge ?? 0.0) - contentView.scrollingPanelOffsetToTopEdge + if update.isReset { + offsetDelta = 0.0 + } + + contentView.scrollingPanelOffsetToTopEdge = update.absoluteOffsetToTopEdge ?? 0.0 + contentView.scrollingPanelOffsetToBottomEdge = update.absoluteOffsetToBottomEdge ?? .greatestFiniteMagnitude + + if let topPanelHeight = self.topPanelHeight, let bottomPanelHeight = self.bottomPanelHeight { + var scrollingPanelOffsetFraction = contentView.scrollingPanelOffsetFraction + + if topPanelHeight > 0.0, let offsetDelta = offsetDelta { + let fractionDelta = -offsetDelta / topPanelHeight + scrollingPanelOffsetFraction = max(0.0, min(1.0, contentView.scrollingPanelOffsetFraction - fractionDelta)) + } + + if bottomPanelHeight > 0.0 && contentView.scrollingPanelOffsetToBottomEdge < bottomPanelHeight { + scrollingPanelOffsetFraction = min(scrollingPanelOffsetFraction, contentView.scrollingPanelOffsetToBottomEdge / bottomPanelHeight) + } else if topPanelHeight > 0.0 && contentView.scrollingPanelOffsetToTopEdge < topPanelHeight { + scrollingPanelOffsetFraction = min(scrollingPanelOffsetFraction, contentView.scrollingPanelOffsetToTopEdge / topPanelHeight) + } + + var transition = update.transition + if !update.isInteracting { + if scrollingPanelOffsetFraction < 0.5 { + scrollingPanelOffsetFraction = 0.0 + } else { + scrollingPanelOffsetFraction = 1.0 + } + if case .none = transition.animation { + } else { + transition = transition.withAnimation(.curve(duration: 0.25, curve: .easeInOut)) + } + } + + if scrollingPanelOffsetFraction != contentView.scrollingPanelOffsetFraction { + contentView.scrollingPanelOffsetFraction = scrollingPanelOffsetFraction + self.state?.updated(transition: transition) + } + + if self.isTopPanelExpanded { + self.isTopPanelExpanded = false + self.component?.isTopPanelExpandedUpdated(self.isTopPanelExpanded, Transition(animation: .curve(duration: 0.25, curve: .easeInOut))) + } + } + } + + private func isTopPanelExpandedUpdated(isExpanded: Bool, transition: Transition) { + if self.isTopPanelExpanded == isExpanded { + return + } + self.isTopPanelExpanded = isExpanded + + self.component?.isTopPanelExpandedUpdated(self.isTopPanelExpanded, transition) + } + + public func collapseTopPanel() { + if !self.isTopPanelExpanded { + return + } + + self.isTopPanelExpandedUpdated(isExpanded: false, transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/Components/ViewControllerComponent/BUILD b/submodules/Components/ViewControllerComponent/BUILD index 0e1e28f483..ca5e4d38f0 100644 --- a/submodules/Components/ViewControllerComponent/BUILD +++ b/submodules/Components/ViewControllerComponent/BUILD @@ -15,6 +15,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AccountContext:AccountContext", "//submodules/TelegramPresentationData:TelegramPresentationData", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", ], visibility = [ "//visibility:public", diff --git a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift index fcf07de3f0..b635d9e54f 100644 --- a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift +++ b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift @@ -5,52 +5,7 @@ import Display import SwiftSignalKit import TelegramPresentationData import AccountContext - -public extension Transition.Animation.Curve { - init(_ curve: ContainedViewLayoutTransitionCurve) { - switch curve { - case .linear: - self = .easeInOut - case .easeInOut: - self = .easeInOut - case .custom: - self = .spring - case .customSpring: - self = .spring - case .spring: - self = .spring - } - } - - var containedViewLayoutTransitionCurve: ContainedViewLayoutTransitionCurve { - switch self { - case .easeInOut: - return .easeInOut - case .spring: - return .spring - } - } -} - -public extension Transition { - init(_ transition: ContainedViewLayoutTransition) { - switch transition { - case .immediate: - self.init(animation: .none) - case let .animated(duration, curve): - self.init(animation: .curve(duration: duration, curve: Transition.Animation.Curve(curve))) - } - } - - var containedViewLayoutTransition: ContainedViewLayoutTransition { - switch self.animation { - case .none: - return .immediate - case let .curve(duration, curve): - return .animated(duration: duration, curve: curve.containedViewLayoutTransitionCurve) - } - } -} +import ComponentDisplayAdapters open class ViewControllerComponentContainer: ViewController { public enum NavigationBarAppearance { @@ -221,7 +176,7 @@ open class ViewControllerComponentContainer: ViewController { private let component: AnyComponent private var presentationDataDisposable: Disposable? - private var validLayout: ContainerViewLayout? + public private(set) var validLayout: ContainerViewLayout? public init(context: AccountContext, component: C, navigationBarAppearance: NavigationBarAppearance, statusBarStyle: StatusBarStyle = .default, theme: PresentationTheme? = nil) where C.EnvironmentType == ViewControllerComponentContainer.Environment { self.context = context diff --git a/submodules/ContactListUI/Sources/ContactsControllerNode.swift b/submodules/ContactListUI/Sources/ContactsControllerNode.swift index 9803afa2eb..109565d468 100644 --- a/submodules/ContactListUI/Sources/ContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsControllerNode.swift @@ -30,7 +30,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/ContextUI/BUILD b/submodules/ContextUI/BUILD index ec5a372e7e..4d25b30910 100644 --- a/submodules/ContextUI/BUILD +++ b/submodules/ContextUI/BUILD @@ -13,12 +13,15 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", + "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/TextSelectionNode:TextSelectionNode", "//submodules/AppBundle:AppBundle", "//submodules/AccountContext:AccountContext", "//submodules/ReactionSelectionNode:ReactionSelectionNode", "//submodules/Markdown:Markdown", + "//submodules/TextFormat:TextFormat", + "//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities", ], visibility = [ "//visibility:public", diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index b4b0647024..8c0697bdcc 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -1,9 +1,13 @@ import Foundation import AsyncDisplayKit import Display +import TelegramCore import TelegramPresentationData import TextSelectionNode +import Markdown import AppBundle +import TextFormat +import TextNodeWithEntities private final class ContextActionsSelectionGestureRecognizer: UIPanGestureRecognizer { var updateLocation: ((CGPoint, Bool) -> Void)? @@ -340,17 +344,37 @@ private final class InnerActionsContainerNode: ASDisplayNode { final class InnerTextSelectionTipContainerNode: ASDisplayNode { private let presentationData: PresentationData private var effectView: UIVisualEffectView? - private let textNode: TextNode + private let highlightBackgroundNode: ASDisplayNode + private let buttonNode: HighlightTrackingButtonNode + private let textNode: TextNodeWithEntities private var textSelectionNode: TextSelectionNode? private let iconNode: ASImageNode + private let placeholderNode: ASDisplayNode private let text: String + private var arguments: TextNodeWithEntities.Arguments? + private var file: TelegramMediaFile? private let targetSelectionIndex: Int? + private var hapticFeedback: HapticFeedback? + + private var action: (() -> Void)? + var requestDismiss: (@escaping () -> Void) -> Void = { _ in } + init(presentationData: PresentationData, tip: ContextController.Tip) { self.presentationData = presentationData - self.textNode = TextNode() + + self.highlightBackgroundNode = ASDisplayNode() + self.highlightBackgroundNode.isAccessibilityElement = false + self.highlightBackgroundNode.alpha = 0.0 + + self.buttonNode = HighlightTrackingButtonNode() + + self.textNode = TextNodeWithEntities() + self.textNode.textNode.displaysAsynchronously = false + self.textNode.textNode.isUserInteractionEnabled = false + var isUserInteractionEnabled = false var icon: UIImage? switch tip { case .textSelection: @@ -372,6 +396,14 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.text = isChannel ? self.presentationData.strings.Conversation_CopyProtectionInfoChannel : self.presentationData.strings.Conversation_CopyProtectionInfoGroup self.targetSelectionIndex = nil icon = UIImage(bundleImageName: "Chat/Context Menu/ReportCopyright") + case let .animatedEmoji(text, arguments, file, action): + self.action = action + self.text = text ?? "" + self.arguments = arguments + self.file = file + self.targetSelectionIndex = nil + icon = nil + isUserInteractionEnabled = text != nil } self.iconNode = ASImageNode() @@ -379,6 +411,11 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.iconNode.displayWithoutProcessing = true self.iconNode.image = generateTintedImage(image: icon, color: presentationData.theme.contextMenu.primaryColor) + self.placeholderNode = ASDisplayNode() + self.placeholderNode.clipsToBounds = true + self.placeholderNode.cornerRadius = 4.0 + self.placeholderNode.isUserInteractionEnabled = false + super.init() self.clipsToBounds = true @@ -386,18 +423,49 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.backgroundColor = presentationData.theme.contextMenu.backgroundColor - let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: presentationData.theme.contextMenu.primaryColor.withAlphaComponent(0.15), knob: presentationData.theme.contextMenu.primaryColor, knobDiameter: 8.0), strings: presentationData.strings, textNode: self.textNode, updateIsActive: { _ in + let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: presentationData.theme.contextMenu.primaryColor.withAlphaComponent(0.15), knob: presentationData.theme.contextMenu.primaryColor, knobDiameter: 8.0), strings: presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { _ in }, present: { _, _ in }, rootNode: self, performAction: { _, _ in }) self.textSelectionNode = textSelectionNode - self.addSubnode(self.textNode) + self.addSubnode(self.highlightBackgroundNode) + self.addSubnode(self.textNode.textNode) self.addSubnode(self.iconNode) + self.addSubnode(self.placeholderNode) self.textSelectionNode.flatMap(self.addSubnode) self.addSubnode(textSelectionNode.highlightAreaNode) + + self.addSubnode(self.buttonNode) + + self.buttonNode.highligthedChanged = { [weak self] highlighted in + guard let strongSelf = self else { + return + } + strongSelf.updateHighlight(animated: true) + } + + self.buttonNode.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) + + let shimmeringForegroundColor: UIColor + if presentationData.theme.overallDarkAppearance { + let backgroundColor = presentationData.theme.contextMenu.backgroundColor.blitOver(presentationData.theme.list.plainBackgroundColor, alpha: 1.0) + shimmeringForegroundColor = presentationData.theme.contextMenu.primaryColor.blitOver(backgroundColor, alpha: 0.1) + } else { + shimmeringForegroundColor = presentationData.theme.contextMenu.primaryColor.withMultipliedAlpha(0.07) + } + + self.placeholderNode.backgroundColor = shimmeringForegroundColor + + self.isUserInteractionEnabled = isUserInteractionEnabled + } + + @objc func pressed() { + self.requestDismiss({ + self.action?() + }) } func updateLayout(widthClass: ContainerViewLayoutSizeClass, width: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { @@ -432,17 +500,62 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { let iconSideInset: CGFloat = 12.0 let textFont = Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 14.0 / 17.0)) + let boldTextFont = Font.bold(floor(presentationData.listsFontSize.baseDisplaySize * 14.0 / 17.0)) + let textColor = self.presentationData.theme.contextMenu.primaryColor + let accentColor = self.presentationData.theme.contextMenu.badgeFillColor let iconSize = self.iconNode.image?.size ?? CGSize(width: 16.0, height: 16.0) + + let text = self.text.replacingOccurrences(of: "#", with: "# ") + let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: boldTextFont, textColor: accentColor), linkAttribute: { _ in + return nil + }))) + if let file = self.file { + let range = (attributedText.string as NSString).range(of: "#") + if range.location != NSNotFound { + attributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), range: range) + } + } - let makeTextLayout = TextNode.asyncLayout(self.textNode) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: self.text, font: textFont, textColor: self.presentationData.theme.contextMenu.primaryColor), backgroundColor: nil, minimumNumberOfLines: 0, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - horizontalInset * 2.0 - iconSize.width - 8.0, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil)) - let _ = textApply() + let shimmeringForegroundColor: UIColor + if presentationData.theme.overallDarkAppearance { + let backgroundColor = presentationData.theme.contextMenu.backgroundColor.blitOver(presentationData.theme.list.plainBackgroundColor, alpha: 1.0) + shimmeringForegroundColor = presentationData.theme.contextMenu.primaryColor.blitOver(backgroundColor, alpha: 0.1) + } else { + shimmeringForegroundColor = presentationData.theme.contextMenu.primaryColor.withMultipliedAlpha(0.07) + } + + let textRightInset: CGFloat + if let _ = self.iconNode.image { + textRightInset = iconSize.width - 8.0 + } else { + textRightInset = 0.0 + } + + let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, minimumNumberOfLines: 0, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - horizontalInset * 2.0 - textRightInset, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil)) + let _ = textApply(self.arguments?.withUpdatedPlaceholderColor(shimmeringForegroundColor)) let textFrame = CGRect(origin: CGPoint(x: horizontalInset, y: verticalInset), size: textLayout.size) - transition.updateFrame(node: self.textNode, frame: textFrame) + transition.updateFrame(node: self.textNode.textNode, frame: textFrame) + if textFrame.size.height.isZero { + self.textNode.textNode.alpha = 0.0 + } else if self.textNode.textNode.alpha.isZero { + self.textNode.textNode.alpha = 1.0 + self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.placeholderNode.layer.animateAlpha(from: self.placeholderNode.alpha, to: 1.0, duration: 0.2) + } - let size = CGSize(width: width, height: textLayout.size.height + verticalInset * 2.0) + var contentHeight = textLayout.size.height + if contentHeight.isZero { + contentHeight = 32.0 + } + + let size = CGSize(width: width, height: contentHeight + verticalInset * 2.0) + + let lineHeight: CGFloat = 8.0 + transition.updateFrame(node: self.placeholderNode, frame: CGRect(origin: CGPoint(x: horizontalInset, y: floorToScreenPixels((size.height - lineHeight) / 2.0)), size: CGSize(width: width - horizontalInset * 2.0, height: lineHeight))) + transition.updateAlpha(node: self.placeholderNode, alpha: textFrame.height.isZero ? 1.0 : 0.0) let iconFrame = CGRect(origin: CGPoint(x: size.width - standardIconWidth - iconSideInset + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) transition.updateFrame(node: self.iconNode, frame: iconFrame) @@ -456,6 +569,10 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { transition.updateFrame(view: effectView, frame: CGRect(origin: CGPoint(), size: size)) } + self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor + self.highlightBackgroundNode.frame = CGRect(origin: CGPoint(), size: size) + self.buttonNode.frame = CGRect(origin: CGPoint(), size: size) + return size } @@ -474,6 +591,55 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { }) } } + + func updateHighlight(animated: Bool) { + if self.buttonNode.isHighlighted || self.isHighlighted { + self.highlightBackgroundNode.alpha = 1.0 + } else { + if animated { + let previousAlpha = self.highlightBackgroundNode.alpha + self.highlightBackgroundNode.alpha = 0.0 + self.highlightBackgroundNode.layer.animateAlpha(from: previousAlpha, to: 0.0, duration: 0.2) + } else { + self.highlightBackgroundNode.alpha = 0.0 + } + } + } + + + var isHighlighted = false + func setHighlighted(_ highlighted: Bool) { + guard self.isHighlighted != highlighted else { + return + } + self.isHighlighted = highlighted + + if highlighted { + if self.hapticFeedback == nil { + self.hapticFeedback = HapticFeedback() + } + self.hapticFeedback?.tap() + } + + self.updateHighlight(animated: false) + } + + func highlightGestureMoved(location: CGPoint) { + if self.bounds.contains(location) && self.isUserInteractionEnabled { + self.setHighlighted(true) + } else { + self.setHighlighted(false) + } + } + + func highlightGestureFinished(performAction: Bool) { + if self.isHighlighted { + self.setHighlighted(false) + if performAction { + self.pressed() + } + } + } } final class ContextActionsContainerNode: ASDisplayNode { @@ -532,7 +698,9 @@ final class ContextActionsContainerNode: ASDisplayNode { self.actionsNode = InnerActionsContainerNode(presentationData: presentationData, items: itemList, getController: getController, actionSelected: actionSelected, requestLayout: requestLayout, feedbackTap: feedbackTap, blurBackground: blurBackground) if let tip = items.tip { let textSelectionTipNode = InnerTextSelectionTipContainerNode(presentationData: presentationData, tip: tip) - textSelectionTipNode.isUserInteractionEnabled = false + textSelectionTipNode.requestDismiss = { completion in + getController()?.dismiss(completion: completion) + } self.textSelectionTipNode = textSelectionTipNode } else { self.textSelectionTipNode = nil diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index a2485302b2..5e655079d0 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -8,6 +8,7 @@ import ReactionSelectionNode import TelegramCore import SwiftSignalKit import AccountContext +import TextNodeWithEntities private let animationDurationFactor: Double = 1.0 @@ -666,8 +667,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi }*/ case let .controller(source): let transitionInfo = source.transitionInfo() - if let transitionInfo = transitionInfo, let (sourceNode, sourceNodeRect) = transitionInfo.sourceNode() { - let contentParentNode = ContextControllerContentNode(sourceNode: sourceNode, controller: source.controller, tapped: { [weak self] in + if let transitionInfo = transitionInfo, let (sourceView, sourceNodeRect) = transitionInfo.sourceNode() { + let contentParentNode = ContextControllerContentNode(sourceView: sourceView, controller: source.controller, tapped: { [weak self] in self?.attemptTransitionControllerIntoNavigation() }) self.contentContainerNode.contentNode = .controller(contentParentNode) @@ -676,7 +677,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi self.contentContainerNode.cornerRadius = 14.0 self.contentContainerNode.addSubnode(contentParentNode) - let projectedFrame = convertFrame(sourceNodeRect, from: sourceNode.view, to: self.view) + let projectedFrame = convertFrame(sourceNodeRect, from: sourceView, to: self.view) self.originalProjectedContentViewFrame = (projectedFrame, projectedFrame) } } @@ -713,8 +714,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi } case let .controller(source): let transitionInfo = source.transitionInfo() - if let transitionInfo = transitionInfo, let (sourceNode, sourceNodeRect) = transitionInfo.sourceNode() { - let projectedFrame = convertFrame(sourceNodeRect, from: sourceNode.view, to: self.view) + if let transitionInfo = transitionInfo, let (sourceView, sourceNodeRect) = transitionInfo.sourceNode() { + let projectedFrame = convertFrame(sourceNodeRect, from: sourceView, to: self.view) self.originalProjectedContentViewFrame = (projectedFrame, projectedFrame) var updatedContentAreaInScreenSpace = transitionInfo.contentAreaInScreenSpace @@ -857,7 +858,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi if let contentNode = self.contentContainerNode.contentNode, case let .controller(controller) = contentNode { let snapshotView: UIView? = nil// controller.sourceNode.view.snapshotContentTree() if let snapshotView = snapshotView { - controller.sourceNode.isHidden = true + controller.sourceView.isHidden = true self.view.insertSubview(snapshotView, belowSubview: self.contentContainerNode.view) snapshotView.layer.animateSpring(from: NSValue(cgPoint: localSourceFrame.center), to: NSValue(cgPoint: CGPoint(x: self.contentContainerNode.frame.midX, y: self.contentContainerNode.frame.minY + localSourceFrame.height / 2.0)), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, removeOnCompletion: false) @@ -1166,8 +1167,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi var completedContentNode = false var completedActionsNode = false - if let transitionInfo = transitionInfo, let (sourceNode, sourceNodeRect) = transitionInfo.sourceNode() { - let projectedFrame = convertFrame(sourceNodeRect, from: sourceNode.view, to: self.view) + if let transitionInfo = transitionInfo, let (sourceView, sourceNodeRect) = transitionInfo.sourceNode() { + let projectedFrame = convertFrame(sourceNodeRect, from: sourceView, to: self.view) self.originalProjectedContentViewFrame = (projectedFrame, projectedFrame) var updatedContentAreaInScreenSpace = transitionInfo.contentAreaInScreenSpace @@ -1251,13 +1252,13 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: contentContainerOffset, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true, completion: { [weak self] _ in completedContentNode = true if let strongSelf = self, let contentNode = strongSelf.contentContainerNode.contentNode, case let .controller(controller) = contentNode { - controller.sourceNode.isHidden = false + controller.sourceView.isHidden = false } intermediateCompletion() }) } else { if let contentNode = self.contentContainerNode.contentNode, case let .controller(controller) = contentNode { - controller.sourceNode.isHidden = false + controller.sourceView.isHidden = false } if let snapshotView = controller.view.snapshotContentTree(keepTransform: true) { @@ -1355,7 +1356,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi private func setItems(items: ContextController.Items, minHeight: ContextController.ActionsHeight?, previousActionsTransition: ContextController.PreviousActionsTransition) { if let presentationNode = self.presentationNode { - presentationNode.replaceItems(items: items, animated: self.didCompleteAnimationIn) + let disableAnimations = self.getController()?.immediateItemsTransitionAnimation == true + presentationNode.replaceItems(items: items, animated: self.didCompleteAnimationIn && !disableAnimations) if !self.didSetItemsReady { self.didSetItemsReady = true @@ -1768,12 +1770,12 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi } } case let .controller(contentParentNode): - var projectedFrame: CGRect = convertFrame(contentParentNode.sourceNode.bounds, from: contentParentNode.sourceNode.view, to: self.view) + var projectedFrame: CGRect = convertFrame(contentParentNode.sourceView.bounds, from: contentParentNode.sourceView, to: self.view) switch self.source { case let .controller(source): let transitionInfo = source.transitionInfo() - if let (sourceNode, sourceRect) = transitionInfo?.sourceNode() { - projectedFrame = convertFrame(sourceRect, from: sourceNode.view, to: self.view) + if let (sourceView, sourceRect) = transitionInfo?.sourceNode() { + projectedFrame = convertFrame(sourceRect, from: sourceView, to: self.view) } default: break @@ -2150,9 +2152,9 @@ public extension ContextExtractedContentSource { public final class ContextControllerTakeControllerInfo { public let contentAreaInScreenSpace: CGRect - public let sourceNode: () -> (ASDisplayNode, CGRect)? + public let sourceNode: () -> (UIView, CGRect)? - public init(contentAreaInScreenSpace: CGRect, sourceNode: @escaping () -> (ASDisplayNode, CGRect)?) { + public init(contentAreaInScreenSpace: CGRect, sourceNode: @escaping () -> (UIView, CGRect)?) { self.contentAreaInScreenSpace = contentAreaInScreenSpace self.sourceNode = sourceNode } @@ -2226,6 +2228,7 @@ public final class ContextController: ViewController, StandalonePresentableContr case textSelection case messageViewsPrivacy case messageCopyProtection(isChannel: Bool) + case animatedEmoji(text: String?, arguments: TextNodeWithEntities.Arguments?, file: TelegramMediaFile?, action: (() -> Void)?) } public final class ActionsHeight { @@ -2393,6 +2396,7 @@ public final class ContextController: ViewController, StandalonePresentableContr public func setItems(_ items: Signal, minHeight: ContextController.ActionsHeight?) { self.items = items if self.isNodeLoaded { + self.immediateItemsTransitionAnimation = false self.controllerNode.setItemsSignal(items: items, minHeight: minHeight, previousActionsTransition: .scale) } } diff --git a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift index c69127b8c1..26ea4f0131 100644 --- a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift @@ -222,7 +222,7 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin self.subtitleNode.attributedText = subtitle.flatMap { subtitle in return NSAttributedString( - string: self.item.text, + string: subtitle, font: subtitleFont, textColor: subtitleColor ) @@ -807,6 +807,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { } final class ItemContainer: ASDisplayNode { + let getController: () -> ContextControllerProtocol? let requestUpdate: (ContainedViewLayoutTransition) -> Void let node: ContextControllerActionsStackItemNode let dimNode: ASDisplayNode @@ -826,6 +827,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { reactionItems: (context: AccountContext, reactionItems: [ReactionContextItem])?, positionLock: CGFloat? ) { + self.getController = getController self.requestUpdate = requestUpdate self.node = item.node( getController: getController, @@ -885,7 +887,9 @@ final class ContextControllerActionsStackNode: ASDisplayNode { if self.tipNode == nil { updatedTransition = .immediate let tipNode = InnerTextSelectionTipContainerNode(presentationData: presentationData, tip: tip) - tipNode.isUserInteractionEnabled = false + tipNode.requestDismiss = { [weak self] completion in + self?.getController()?.dismiss(completion: completion) + } self.tipNode = tipNode } @@ -908,10 +912,17 @@ final class ContextControllerActionsStackNode: ASDisplayNode { } func highlightGestureMoved(location: CGPoint) { + if let tipNode = self.tipNode { + let tipLocation = self.view.convert(location, to: tipNode.view) + tipNode.highlightGestureMoved(location: tipLocation) + } self.node.highlightGestureMoved(location: self.view.convert(location, to: self.node.view)) } func highlightGestureFinished(performAction: Bool) { + if let tipNode = self.tipNode { + tipNode.highlightGestureFinished(performAction: performAction) + } self.node.highlightGestureFinished(performAction: performAction) } } @@ -993,6 +1004,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { if animated { self.dismissingItemContainers.append((itemContainer, false)) } else { + itemContainer.tipNode?.removeFromSupernode() itemContainer.removeFromSupernode() } } @@ -1194,6 +1206,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { itemContainer?.removeFromSupernode() }) if let tipNode = itemContainer.tipNode { + transition.updateFrame(node: tipNode, frame: CGRect(origin: CGPoint(x: navigationContainerFrame.minX, y: navigationContainerFrame.maxY + tipSpacing), size: tipNode.frame.size), beginWithCurrentState: true) transition.updateAlpha(node: tipNode, alpha: 0.0, completion: { [weak tipNode] _ in tipNode?.removeFromSupernode() }) diff --git a/submodules/ContextUI/Sources/PeekController.swift b/submodules/ContextUI/Sources/PeekController.swift index 78950898b7..615979d884 100644 --- a/submodules/ContextUI/Sources/PeekController.swift +++ b/submodules/ContextUI/Sources/PeekController.swift @@ -60,7 +60,7 @@ public final class PeekController: ViewController, ContextControllerProtocol { private let presentationData: PresentationData private let content: PeekControllerContent - var sourceNode: () -> ASDisplayNode? + var sourceView: () -> (UIView, CGRect)? public var visibilityUpdated: ((Bool) -> Void)? @@ -68,10 +68,15 @@ public final class PeekController: ViewController, ContextControllerProtocol { private var animatedIn = false - public init(presentationData: PresentationData, content: PeekControllerContent, sourceNode: @escaping () -> ASDisplayNode?) { + private let _ready = Promise() + override public var ready: Promise { + return self._ready + } + + public init(presentationData: PresentationData, content: PeekControllerContent, sourceView: @escaping () -> (UIView, CGRect)?) { self.presentationData = presentationData self.content = content - self.sourceNode = sourceNode + self.sourceView = sourceView super.init(navigationBarPresentationData: nil) @@ -90,8 +95,8 @@ public final class PeekController: ViewController, ContextControllerProtocol { } private func getSourceRect() -> CGRect { - if let sourceNode = self.sourceNode() { - return sourceNode.view.convert(sourceNode.bounds, to: self.view) + if let (sourceView, sourceRect) = self.sourceView() { + return sourceView.convert(sourceRect, to: self.view) } else { let size = self.displayNode.bounds.size return CGRect(origin: CGPoint(x: floor((size.width - 10.0) / 2.0), y: floor((size.height - 10.0) / 2.0)), size: CGSize(width: 10.0, height: 10.0)) diff --git a/submodules/ContextUI/Sources/PeekControllerContent.swift b/submodules/ContextUI/Sources/PeekControllerContent.swift index ba9b23d524..f5b877fc12 100644 --- a/submodules/ContextUI/Sources/PeekControllerContent.swift +++ b/submodules/ContextUI/Sources/PeekControllerContent.swift @@ -2,6 +2,7 @@ import Foundation import UIKit import AsyncDisplayKit import Display +import SwiftSignalKit public enum PeekControllerContentPresentation { case contained @@ -26,6 +27,7 @@ public protocol PeekControllerContent { } public protocol PeekControllerContentNode { + func ready() -> Signal func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize } diff --git a/submodules/ContextUI/Sources/PeekControllerGestureRecognizer.swift b/submodules/ContextUI/Sources/PeekControllerGestureRecognizer.swift index 623cad78ff..a766664a2c 100644 --- a/submodules/ContextUI/Sources/PeekControllerGestureRecognizer.swift +++ b/submodules/ContextUI/Sources/PeekControllerGestureRecognizer.swift @@ -18,8 +18,8 @@ private func traceDeceleratingScrollView(_ view: UIView, at point: CGPoint) -> B } public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer { - private let contentAtPoint: (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>? - private let present: (PeekControllerContent, ASDisplayNode) -> ViewController? + private let contentAtPoint: (CGPoint) -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError>? + private let present: (PeekControllerContent, UIView, CGRect) -> ViewController? private let updateContent: (PeekControllerContent?) -> Void private let activateBySingleTap: Bool public var checkSingleTapActivationAtPoint: ((CGPoint) -> Bool)? @@ -29,16 +29,16 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer { private var pressTimer: SwiftSignalKit.Timer? private let candidateContentDisposable = MetaDisposable() - private var candidateContent: (ASDisplayNode, PeekControllerContent)? { + private var candidateContent: (UIView, CGRect, PeekControllerContent)? { didSet { - self.updateContent(self.candidateContent?.1) + self.updateContent(self.candidateContent?.2) } } private var menuActivation: PeerControllerMenuActivation? private weak var presentedController: PeekController? - public init(contentAtPoint: @escaping (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>?, present: @escaping (PeekControllerContent, ASDisplayNode) -> ViewController?, updateContent: @escaping (PeekControllerContent?) -> Void = { _ in }, activateBySingleTap: Bool = false) { + public init(contentAtPoint: @escaping (CGPoint) -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError>?, present: @escaping (PeekControllerContent, UIView, CGRect) -> ViewController?, updateContent: @escaping (PeekControllerContent?) -> Void = { _ in }, activateBySingleTap: Bool = false) { self.contentAtPoint = contentAtPoint self.present = present self.updateContent = updateContent @@ -254,21 +254,21 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer { } //print("check received, will process: \(processResult), force: \(forceActivate), state: \(strongSelf.state)") if processResult { - if let (sourceNode, content) = result { + if let (sourceView, sourceRect, content) = result { if let currentContent = strongSelf.candidateContent { - if !currentContent.1.isEqual(to: content) { + if !currentContent.2.isEqual(to: content) { strongSelf.tapLocation = touchLocation - strongSelf.candidateContent = (sourceNode, content) + strongSelf.candidateContent = (sourceView, sourceRect, content) strongSelf.menuActivation = content.menuActivation() if let presentedController = strongSelf.presentedController, presentedController.isNodeLoaded { - presentedController.sourceNode = { - return sourceNode + presentedController.sourceView = { + return (sourceView, sourceRect) } (presentedController.displayNode as? PeekControllerNode)?.updateContent(content: content) } } } else { - if let presentedController = strongSelf.present(content, sourceNode) { + if let presentedController = strongSelf.present(content, sourceView, sourceRect) { if let presentedController = presentedController as? PeekController { if forceActivate { strongSelf.candidateContent = nil @@ -276,7 +276,7 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer { (presentedController.displayNode as? PeekControllerNode)?.activateMenu() } } else { - strongSelf.candidateContent = (sourceNode, content) + strongSelf.candidateContent = (sourceView, sourceRect, content) strongSelf.menuActivation = content.menuActivation() strongSelf.presentedController = presentedController diff --git a/submodules/ContextUI/Sources/PeekControllerNode.swift b/submodules/ContextUI/Sources/PeekControllerNode.swift index d53a35f73a..af9503a098 100644 --- a/submodules/ContextUI/Sources/PeekControllerNode.swift +++ b/submodules/ContextUI/Sources/PeekControllerNode.swift @@ -126,6 +126,8 @@ final class PeekControllerNode: ViewControllerTracingNode { } self.hapticFeedback.prepareTap() + + controller.ready.set(self.contentNode.ready()) } deinit { diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index 3eb015fef5..851dbc92e8 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -291,7 +291,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -371,7 +371,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(logData.count), attributes: [.FileName(fileName: "Log-iOS-Short.txt")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -457,7 +457,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -541,7 +541,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -625,7 +625,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -678,7 +678,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { let messages = logs.map { (name, path) -> EnqueueMessage in let id = Int64.random(in: Int64.min ... Int64.max) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)]) - return .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + return .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) } let _ = enqueueMessages(account: context.account, peerId: peerId, messages: messages).start() } @@ -786,7 +786,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/zip", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-All.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } @@ -1388,7 +1388,7 @@ public func triggerDebugSendLogsUI(context: AccountContext, additionalInfo: Stri context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } diff --git a/submodules/Display/Source/ActionSheetTextItem.swift b/submodules/Display/Source/ActionSheetTextItem.swift index 07d9d06d03..b13d4f3240 100644 --- a/submodules/Display/Source/ActionSheetTextItem.swift +++ b/submodules/Display/Source/ActionSheetTextItem.swift @@ -50,6 +50,7 @@ public class ActionSheetTextNode: ActionSheetItemNode { self.label.displaysAsynchronously = false self.label.truncationType = .end self.label.isAccessibilityElement = false + self.label.textAlignment = .center self.accessibilityArea = AccessibilityAreaNode() self.accessibilityArea.accessibilityTraits = .staticText diff --git a/submodules/Display/Source/AlertController.swift b/submodules/Display/Source/AlertController.swift index f57b2359ec..35b6975c78 100644 --- a/submodules/Display/Source/AlertController.swift +++ b/submodules/Display/Source/AlertController.swift @@ -89,7 +89,7 @@ open class AlertController: ViewController, StandalonePresentableController { private weak var existingAlertController: AlertController? public var willDismiss: (() -> Void)? - public var dismissed: (() -> Void)? + public var dismissed: ((Bool) -> Void)? public init(theme: AlertControllerTheme, contentNode: AlertContentNode, existingAlertController: AlertController? = nil, allowInputInset: Bool = true) { self.theme = theme @@ -108,6 +108,7 @@ open class AlertController: ViewController, StandalonePresentableController { fatalError("init(coder:) has not been implemented") } + private var isDismissed = false override open func loadDisplayNode() { self.displayNode = AlertControllerNode(contentNode: self.contentNode, theme: self.theme, allowInputInset: self.allowInputInset) self.displayNodeDidLoad() @@ -118,6 +119,8 @@ open class AlertController: ViewController, StandalonePresentableController { if let strongSelf = self, strongSelf.contentNode.dismissOnOutsideTap { strongSelf.willDismiss?() strongSelf.controllerNode.animateOut { + self?.dismissed?(true) + self?.isDismissed = true self?.dismiss() } } @@ -140,7 +143,10 @@ open class AlertController: ViewController, StandalonePresentableController { } override open func dismiss(completion: (() -> Void)? = nil) { - self.dismissed?() + if !self.isDismissed { + self.isDismissed = true + self.dismissed?(false) + } self.presentingViewController?.dismiss(animated: false, completion: completion) } diff --git a/submodules/Display/Source/CAAnimationUtils.swift b/submodules/Display/Source/CAAnimationUtils.swift index c67008417d..77f1390c67 100644 --- a/submodules/Display/Source/CAAnimationUtils.swift +++ b/submodules/Display/Source/CAAnimationUtils.swift @@ -62,7 +62,7 @@ private func adjustFrameRate(animation: CAAnimation) { } public extension CALayer { - func makeAnimation(from: AnyObject, to: AnyObject, keyPath: String, timingFunction: String, duration: Double, delay: Double = 0.0, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) -> CAAnimation { + func makeAnimation(from: AnyObject?, to: AnyObject, keyPath: String, timingFunction: String, duration: Double, delay: Double = 0.0, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) -> CAAnimation { if timingFunction.hasPrefix(kCAMediaTimingFunctionCustomSpringPrefix) { let components = timingFunction.components(separatedBy: "_") let damping = Float(components[1]) ?? 100.0 @@ -158,7 +158,7 @@ public extension CALayer { } } - func animate(from: AnyObject, to: AnyObject, keyPath: String, timingFunction: String, duration: Double, delay: Double = 0.0, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { + func animate(from: AnyObject?, to: AnyObject, keyPath: String, timingFunction: String, duration: Double, delay: Double = 0.0, mediaTimingFunction: CAMediaTimingFunction? = nil, removeOnCompletion: Bool = true, additive: Bool = false, completion: ((Bool) -> Void)? = nil) { let animation = self.makeAnimation(from: from, to: to, keyPath: keyPath, timingFunction: timingFunction, duration: duration, delay: delay, mediaTimingFunction: mediaTimingFunction, removeOnCompletion: removeOnCompletion, additive: additive, completion: completion) self.add(animation, forKey: additive ? nil : keyPath) } diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index 6ec8dccddc..5cbc895b8c 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -146,13 +146,15 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "position") + node.layer.removeAnimation(forKey: "bounds") node.frame = frame if let completion = completion { completion(true) } case let .animated(duration, curve): let previousFrame: CGRect - if beginWithCurrentState, let presentation = node.layer.presentation() { + if beginWithCurrentState, (node.layer.animation(forKey: "position") != nil || node.layer.animation(forKey: "bounds") != nil), let presentation = node.layer.presentation() { previousFrame = presentation.frame } else { previousFrame = node.frame @@ -173,6 +175,8 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "position") + node.layer.removeAnimation(forKey: "bounds") node.position = frame.center node.bounds = CGRect(origin: CGPoint(), size: frame.size) if let completion = completion { @@ -206,6 +210,8 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + layer.removeAnimation(forKey: "position") + layer.removeAnimation(forKey: "bounds") layer.position = frame.center layer.bounds = CGRect(origin: CGPoint(), size: frame.size) if let completion = completion { @@ -277,13 +283,14 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "bounds") node.bounds = bounds if let completion = completion { completion(true) } case let .animated(duration, curve): let previousBounds: CGRect - if beginWithCurrentState, let presentation = node.layer.presentation() { + if beginWithCurrentState, node.layer.animation(forKey: "bounds") != nil, let presentation = node.layer.presentation() { previousBounds = presentation.bounds } else { previousBounds = node.bounds @@ -304,6 +311,7 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + layer.removeAnimation(forKey: "bounds") layer.bounds = bounds if let completion = completion { completion(true) @@ -326,14 +334,15 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "position") node.position = position if let completion = completion { completion(true) } case let .animated(duration, curve): let previousPosition: CGPoint - if beginWithCurrentState { - previousPosition = node.layer.presentation()?.position ?? node.position + if beginWithCurrentState, node.layer.animation(forKey: "position") != nil, let presentation = node.layer.presentation() { + previousPosition = presentation.position } else { previousPosition = node.position } @@ -353,6 +362,7 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + layer.removeAnimation(forKey: "position") layer.position = position if let completion = completion { completion(true) @@ -615,13 +625,15 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + //view.layer.removeAnimation(forKey: "position") + //view.layer.removeAnimation(forKey: "bounds") view.frame = frame if let completion = completion { completion(true) } case let .animated(duration, curve): let previousFrame: CGRect - if beginWithCurrentState, let presentation = view.layer.presentation() { + if beginWithCurrentState, (view.layer.animation(forKey: "position") != nil || view.layer.animation(forKey: "bounds") != nil), let presentation = view.layer.presentation() { previousFrame = presentation.frame } else { previousFrame = view.frame @@ -642,13 +654,15 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + layer.removeAnimation(forKey: "position") + layer.removeAnimation(forKey: "bounds") layer.frame = frame if let completion = completion { completion(true) } case let .animated(duration, curve): let previousFrame: CGRect - if beginWithCurrentState, let presentation = layer.presentation() { + if beginWithCurrentState, (layer.animation(forKey: "position") != nil || layer.animation(forKey: "bounds") != nil), let presentation = layer.presentation() { previousFrame = presentation.frame } else { previousFrame = layer.frame @@ -790,6 +804,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + node.layer.removeAnimation(forKey: "cornerRadius") node.cornerRadius = cornerRadius if let completion = completion { completion(true) @@ -815,6 +830,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + layer.removeAnimation(forKey: "cornerRadius") layer.cornerRadius = cornerRadius if let completion = completion { completion(true) @@ -1084,6 +1100,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + node.layer.removeAnimation(forKey: "sublayerTransform") node.layer.sublayerTransform = CATransform3DMakeScale(scale, scale, 1.0) if let completion = completion { completion(true) @@ -1116,6 +1133,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + node.layer.removeAnimation(forKey: "sublayerTransform") node.layer.sublayerTransform = CATransform3DMakeScale(scale, scale, 1.0) if let completion = completion { completion(true) @@ -1153,6 +1171,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + node.layer.removeAnimation(forKey: "sublayerTransform") node.layer.sublayerTransform = transform if let completion = completion { completion(true) @@ -1200,6 +1219,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + layer.removeAnimation(forKey: "sublayerTransform") layer.sublayerTransform = CATransform3DMakeScale(scale.x, scale.y, 1.0) if let completion = completion { completion(true) @@ -1248,6 +1268,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + layer.removeAnimation(forKey: "transform") layer.transform = CATransform3DMakeScale(scale.x, scale.y, 1.0) if let completion = completion { completion(true) @@ -1275,6 +1296,7 @@ public extension ContainedViewLayoutTransition { switch self { case .immediate: + layer.removeAnimation(forKey: "sublayerTransform") layer.sublayerTransform = CATransform3DMakeTranslation(offset.x, offset.y, 0.0) if let completion = completion { completion(true) diff --git a/submodules/Display/Source/ContextContentSourceNode.swift b/submodules/Display/Source/ContextContentSourceNode.swift index 8e44c9e681..b4ed6a4cbd 100644 --- a/submodules/Display/Source/ContextContentSourceNode.swift +++ b/submodules/Display/Source/ContextContentSourceNode.swift @@ -115,12 +115,12 @@ public final class ContextExtractedContentView: UIView { } public final class ContextControllerContentNode: ASDisplayNode { - public let sourceNode: ASDisplayNode + public let sourceView: UIView public let controller: ViewController private let tapped: () -> Void - public init(sourceNode: ASDisplayNode, controller: ViewController, tapped: @escaping () -> Void) { - self.sourceNode = sourceNode + public init(sourceView: UIView, controller: ViewController, tapped: @escaping () -> Void) { + self.sourceView = sourceView self.controller = controller self.tapped = tapped diff --git a/submodules/Display/Source/ContextControllerSourceNode.swift b/submodules/Display/Source/ContextControllerSourceNode.swift index 5429722f3b..0bfd0ce673 100644 --- a/submodules/Display/Source/ContextControllerSourceNode.swift +++ b/submodules/Display/Source/ContextControllerSourceNode.swift @@ -271,7 +271,9 @@ open class ContextControllerSourceView: UIView { public weak var additionalActivationProgressLayer: CALayer? public var targetNodeForActivationProgress: ASDisplayNode? public var targetViewForActivationProgress: UIView? + public weak var targetLayerForActivationProgress: CALayer? public var targetNodeForActivationProgressContentRect: CGRect? + public var useSublayerTransformForActivation: Bool = true override public init(frame: CGRect) { super.init(frame: frame) @@ -297,35 +299,42 @@ open class ContextControllerSourceView: UIView { if let customActivationProgress = strongSelf.customActivationProgress { customActivationProgress(progress, update) } else if strongSelf.animateScale { - let targetView: UIView + let targetLayer: CALayer let targetContentRect: CGRect if let targetNodeForActivationProgress = strongSelf.targetNodeForActivationProgress { - targetView = targetNodeForActivationProgress.view + targetLayer = targetNodeForActivationProgress.layer if let targetNodeForActivationProgressContentRect = strongSelf.targetNodeForActivationProgressContentRect { targetContentRect = targetNodeForActivationProgressContentRect } else { - targetContentRect = CGRect(origin: CGPoint(), size: targetView.bounds.size) + targetContentRect = CGRect(origin: CGPoint(), size: targetLayer.bounds.size) } } else if let targetViewForActivationProgress = strongSelf.targetViewForActivationProgress { - targetView = targetViewForActivationProgress + targetLayer = targetViewForActivationProgress.layer if let targetNodeForActivationProgressContentRect = strongSelf.targetNodeForActivationProgressContentRect { targetContentRect = targetNodeForActivationProgressContentRect } else { - targetContentRect = CGRect(origin: CGPoint(), size: targetView.bounds.size) + targetContentRect = CGRect(origin: CGPoint(), size: targetLayer.bounds.size) + } + } else if let targetLayerForActivationProgress = strongSelf.targetLayerForActivationProgress { + targetLayer = targetLayerForActivationProgress + if let targetNodeForActivationProgressContentRect = strongSelf.targetNodeForActivationProgressContentRect { + targetContentRect = targetNodeForActivationProgressContentRect + } else { + targetContentRect = CGRect(origin: CGPoint(), size: targetLayer.bounds.size) } } else { - targetView = strongSelf - targetContentRect = CGRect(origin: CGPoint(), size: targetView.bounds.size) + targetLayer = strongSelf.layer + targetContentRect = CGRect(origin: CGPoint(), size: targetLayer.bounds.size) } let scaleSide = targetContentRect.width let minScale: CGFloat = max(0.7, (scaleSide - 15.0) / scaleSide) let currentScale = 1.0 * (1.0 - progress) + minScale * progress - let originalCenterOffsetX: CGFloat = targetView.bounds.width / 2.0 - targetContentRect.midX + let originalCenterOffsetX: CGFloat = targetLayer.bounds.width / 2.0 - targetContentRect.midX let scaledCenterOffsetX: CGFloat = originalCenterOffsetX * currentScale - let originalCenterOffsetY: CGFloat = targetView.bounds.height / 2.0 - targetContentRect.midY + let originalCenterOffsetY: CGFloat = targetLayer.bounds.height / 2.0 - targetContentRect.midY let scaledCenterOffsetY: CGFloat = originalCenterOffsetY * currentScale let scaleMidX: CGFloat = scaledCenterOffsetX - originalCenterOffsetX @@ -334,22 +343,38 @@ open class ContextControllerSourceView: UIView { switch update { case .update: let sublayerTransform = CATransform3DTranslate(CATransform3DScale(CATransform3DIdentity, currentScale, currentScale, 1.0), scaleMidX, scaleMidY, 0.0) - targetView.layer.sublayerTransform = sublayerTransform + if strongSelf.useSublayerTransformForActivation { + targetLayer.sublayerTransform = sublayerTransform + } else { + targetLayer.transform = sublayerTransform + } if let additionalActivationProgressLayer = strongSelf.additionalActivationProgressLayer { additionalActivationProgressLayer.transform = sublayerTransform } case .begin: let sublayerTransform = CATransform3DTranslate(CATransform3DScale(CATransform3DIdentity, currentScale, currentScale, 1.0), scaleMidX, scaleMidY, 0.0) - targetView.layer.sublayerTransform = sublayerTransform + if strongSelf.useSublayerTransformForActivation { + targetLayer.sublayerTransform = sublayerTransform + } else { + targetLayer.transform = sublayerTransform + } if let additionalActivationProgressLayer = strongSelf.additionalActivationProgressLayer { additionalActivationProgressLayer.transform = sublayerTransform } case .ended: let sublayerTransform = CATransform3DTranslate(CATransform3DScale(CATransform3DIdentity, currentScale, currentScale, 1.0), scaleMidX, scaleMidY, 0.0) - let previousTransform = targetView.layer.sublayerTransform - targetView.layer.sublayerTransform = sublayerTransform - targetView.layer.animate(from: NSValue(caTransform3D: previousTransform), to: NSValue(caTransform3D: sublayerTransform), keyPath: "sublayerTransform", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2) + if strongSelf.useSublayerTransformForActivation { + let previousTransform = targetLayer.sublayerTransform + targetLayer.sublayerTransform = sublayerTransform + + targetLayer.animate(from: NSValue(caTransform3D: previousTransform), to: NSValue(caTransform3D: sublayerTransform), keyPath: "sublayerTransform", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2) + } else { + let previousTransform = targetLayer.transform + targetLayer.transform = sublayerTransform + + targetLayer.animate(from: NSValue(caTransform3D: previousTransform), to: NSValue(caTransform3D: sublayerTransform), keyPath: "transform", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: 0.2) + } if let additionalActivationProgressLayer = strongSelf.additionalActivationProgressLayer { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { diff --git a/submodules/Display/Source/ContextGesture.swift b/submodules/Display/Source/ContextGesture.swift index 7e2eedc52c..217df908aa 100644 --- a/submodules/Display/Source/ContextGesture.swift +++ b/submodules/Display/Source/ContextGesture.swift @@ -20,9 +20,12 @@ private class TimerTargetWrapper: NSObject { } } -public func cancelParentGestures(view: UIView) { +public func cancelParentGestures(view: UIView, ignore: [UIGestureRecognizer] = []) { if let gestureRecognizers = view.gestureRecognizers { for recognizer in gestureRecognizers { + if ignore.contains(where: { $0 === recognizer }) { + continue + } recognizer.state = .failed } } @@ -33,7 +36,7 @@ public func cancelParentGestures(view: UIView) { node.highligthedChanged(false) } if let superview = view.superview { - cancelParentGestures(view: superview) + cancelParentGestures(view: superview, ignore: ignore) } } @@ -66,6 +69,7 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg public var externalUpdated: ((UIView?, CGPoint) -> Void)? public var externalEnded: (((UIView?, CGPoint)?) -> Void)? public var activatedAfterCompletion: (() -> Void)? + public var cancelGesturesOnActivation: (() -> Void)? override public init(target: Any?, action: Selector?) { super.init(target: target, action: action) @@ -142,11 +146,12 @@ public final class ContextGesture: UIGestureRecognizer, UIGestureRecognizerDeleg strongSelf.animator?.invalidate() strongSelf.activated?(strongSelf, location) strongSelf.wasActivated = true - if let view = strongSelf.view?.superview { + if let view = strongSelf.view { if let window = view.window { cancelOtherGestures(gesture: strongSelf, view: window) } - cancelParentGestures(view: view) + strongSelf.cancelGesturesOnActivation?() + cancelParentGestures(view: view, ignore: [strongSelf]) } strongSelf.state = .began default: diff --git a/submodules/Display/Source/DeviceMetrics.swift b/submodules/Display/Source/DeviceMetrics.swift index 3a3c2f00fb..4d01d7ac2c 100644 --- a/submodules/Display/Source/DeviceMetrics.swift +++ b/submodules/Display/Source/DeviceMetrics.swift @@ -16,6 +16,10 @@ public enum DeviceMetrics: CaseIterable, Equatable { case iPhone12Mini case iPhone12 case iPhone12ProMax + case iPhone13Mini + case iPhone13 + case iPhone13Pro + case iPhone13ProMax case iPad case iPadMini case iPad102Inch @@ -38,6 +42,10 @@ public enum DeviceMetrics: CaseIterable, Equatable { .iPhone12Mini, .iPhone12, .iPhone12ProMax, + .iPhone13Mini, + .iPhone13, + .iPhone13Pro, + .iPhone13ProMax, .iPad, .iPadMini, .iPad102Inch, @@ -113,6 +121,14 @@ public enum DeviceMetrics: CaseIterable, Equatable { return CGSize(width: 390.0, height: 844.0) case .iPhone12ProMax: return CGSize(width: 428.0, height: 926.0) + case .iPhone13Mini: + return CGSize(width: 375.0, height: 812.0) + case .iPhone13: + return CGSize(width: 390.0, height: 844.0) + case .iPhone13Pro: + return CGSize(width: 390.0, height: 844.0) + case .iPhone13ProMax: + return CGSize(width: 428.0, height: 926.0) case .iPad: return CGSize(width: 768.0, height: 1024.0) case .iPadMini: @@ -140,9 +156,9 @@ public enum DeviceMetrics: CaseIterable, Equatable { return 41.0 + UIScreenPixel case .iPhone12Mini: return 44.0 - case .iPhone12: + case .iPhone12, .iPhone13, .iPhone13Pro: return 47.0 + UIScreenPixel - case .iPhone12ProMax: + case .iPhone12ProMax, .iPhone13ProMax: return 53.0 + UIScreenPixel case let .unknown(_, _, onScreenNavigationHeight): if let _ = onScreenNavigationHeight { @@ -157,7 +173,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { func safeInsets(inLandscape: Bool) -> UIEdgeInsets { switch self { - case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return inLandscape ? UIEdgeInsets(top: 0.0, left: 44.0, bottom: 0.0, right: 44.0) : UIEdgeInsets(top: 44.0, left: 0.0, bottom: 0.0, right: 0.0) default: return UIEdgeInsets.zero @@ -166,7 +182,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { func onScreenNavigationHeight(inLandscape: Bool, systemOnScreenNavigationHeight: CGFloat?) -> CGFloat? { switch self { - case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return inLandscape ? 21.0 : 34.0 case .iPadPro3rdGen, .iPadPro11Inch: return 21.0 @@ -198,7 +214,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { var statusBarHeight: CGFloat { switch self { - case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return 44.0 case .iPadPro11Inch, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen: return 24.0 @@ -216,7 +232,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { return 162.0 case .iPhone6, .iPhone6Plus: return 163.0 - case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return 172.0 case .iPad, .iPad102Inch, .iPadPro10Inch: return 348.0 @@ -235,9 +251,9 @@ public enum DeviceMetrics: CaseIterable, Equatable { return 216.0 case .iPhone6Plus: return 226.0 - case .iPhoneX, .iPhone12Mini, .iPhone12: - return 291.0 - case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax: + case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro: + return 292.0 + case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax: return 302.0 case .iPad, .iPad102Inch, .iPadPro10Inch: return 263.0 @@ -256,7 +272,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { func predictiveInputHeight(inLandscape: Bool) -> CGFloat { if inLandscape { switch self { - case .iPhone4, .iPhone5, .iPhone6, .iPhone6Plus, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhone4, .iPhone5, .iPhone6, .iPhone6Plus, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return 37.0 case .iPad, .iPad102Inch, .iPadPro10Inch, .iPadPro11Inch, .iPadPro, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen: return 50.0 @@ -267,7 +283,7 @@ public enum DeviceMetrics: CaseIterable, Equatable { switch self { case .iPhone4, .iPhone5: return 37.0 - case .iPhone6, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax: + case .iPhone6, .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax: return 44.0 case .iPhone6Plus: return 45.0 diff --git a/submodules/Display/Source/GridNode.swift b/submodules/Display/Source/GridNode.swift index 6b833112c1..eef5d88868 100644 --- a/submodules/Display/Source/GridNode.swift +++ b/submodules/Display/Source/GridNode.swift @@ -552,9 +552,9 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { } itemSize.height = height } else if let fillsRowWithDynamicHeight = item.fillsRowWithDynamicHeight { - let height = fillsRowWithDynamicHeight(gridLayout.size.width) + let height = fillsRowWithDynamicHeight(gridLayout.size.width - itemInsets.left - itemInsets.right) nextItemOrigin.x = initialSpacing + itemInsets.left - itemSize.width = gridLayout.size.width + itemSize.width = gridLayout.size.width - itemInsets.left - itemInsets.right itemSize.height = height } else if index == 0 { let itemsInRow = max(1, Int(effectiveWidth) / Int(itemSize.width)) diff --git a/submodules/Display/Source/GridNodeScroller.swift b/submodules/Display/Source/GridNodeScroller.swift index 22a778f6e8..dc884cf79c 100644 --- a/submodules/Display/Source/GridNodeScroller.swift +++ b/submodules/Display/Source/GridNodeScroller.swift @@ -6,12 +6,12 @@ private class GridNodeScrollerLayer: CALayer { } } -private class GridNodeScrollerView: UIScrollView { - override class var layerClass: AnyClass { +public class GridNodeScrollerView: UIScrollView { + override public class var layerClass: AnyClass { return GridNodeScrollerLayer.self } - override init(frame: CGRect) { + override public init(frame: CGRect) { super.init(frame: frame) if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { @@ -19,15 +19,15 @@ private class GridNodeScrollerView: UIScrollView { } } - required init?(coder aDecoder: NSCoder) { + required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } - override func touchesShouldCancel(in view: UIView) -> Bool { + override public func touchesShouldCancel(in view: UIView) -> Bool { return true } - @objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + @objc private func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return false } } diff --git a/submodules/Display/Source/HapticFeedback.swift b/submodules/Display/Source/HapticFeedback.swift index bad8b9c59b..a0a714adaf 100644 --- a/submodules/Display/Source/HapticFeedback.swift +++ b/submodules/Display/Source/HapticFeedback.swift @@ -122,11 +122,12 @@ private final class HapticFeedbackImpl { } func warning() { - if let notificationGenerator = self.notificationGenerator { - notificationGenerator.notificationOccurred(.warning) - } else { - - } + AudioServicesPlaySystemSound(1102) +// if let notificationGenerator = self.notificationGenerator { +// notificationGenerator.notificationOccurred(.warning) +// } else { +// +// } } @objc dynamic func f() { diff --git a/submodules/Display/Source/ImmediateTextNode.swift b/submodules/Display/Source/ImmediateTextNode.swift index b7dae91235..53b456c4c6 100644 --- a/submodules/Display/Source/ImmediateTextNode.swift +++ b/submodules/Display/Source/ImmediateTextNode.swift @@ -5,6 +5,12 @@ public struct ImmediateTextNodeLayoutInfo { public let size: CGSize public let truncated: Bool public let numberOfLines: Int + + public init(size: CGSize, truncated: Bool, numberOfLines: Int) { + self.size = size + self.truncated = truncated + self.numberOfLines = numberOfLines + } } public class ImmediateTextNode: TextNode { @@ -125,7 +131,7 @@ public class ImmediateTextNode: TextNode { } } - override public func didLoad() { + override open func didLoad() { super.didLoad() self.updateInteractiveActions() diff --git a/submodules/Display/Source/Navigation/NavigationController.swift b/submodules/Display/Source/Navigation/NavigationController.swift index 43e43813bc..7de91ddaf2 100644 --- a/submodules/Display/Source/Navigation/NavigationController.swift +++ b/submodules/Display/Source/Navigation/NavigationController.swift @@ -357,41 +357,10 @@ open class NavigationController: UINavigationController, ContainableController, self.updateContainers(layout: layout, transition: transition) } } - - private var forceBadgeHidden = false - public func setForceBadgeHidden(_ hidden: Bool) { - guard hidden != self.forceBadgeHidden else { - return - } - self.forceBadgeHidden = hidden - if let layout = self.validLayout { - self.updateBadgeVisibility(layout: layout) - } - } - - private func updateBadgeVisibility(layout: ContainerViewLayout) { - guard let badgeNode = self.badgeNode else { - return - } - let badgeIsHidden = !layout.deviceMetrics.hasTopNotch || self.forceBadgeHidden || layout.size.width > layout.size.height - if badgeIsHidden != badgeNode.isHidden && !badgeIsHidden { - Queue.mainQueue().after(0.3) { - badgeNode.isHidden = badgeIsHidden - } - } else { - badgeNode.isHidden = badgeIsHidden - } - } - private func updateContainers(layout rawLayout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { self.isUpdatingContainers = true - - if let badgeNode = self.badgeNode, let image = badgeNode.image { - self.updateBadgeVisibility(layout: rawLayout) - badgeNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((rawLayout.size.width - image.size.width) / 2.0), y: 6.0), size: image.size) - } - + var layout = rawLayout if self.ignoreInputHeight { @@ -938,7 +907,7 @@ open class NavigationController: UINavigationController, ContainableController, rootModalFrame.updateDismissal(transition: transition, progress: effectiveRootModalDismissProgress, additionalProgress: additionalModalFrameProgress, completion: {}) forceStatusBarAnimation = true } else { - rootModalFrame = NavigationModalFrame(theme: self.theme) + rootModalFrame = NavigationModalFrame() self.rootModalFrame = rootModalFrame if let rootContainer = self.rootContainer { var rootContainerNode: ASDisplayNode @@ -1268,16 +1237,8 @@ open class NavigationController: UINavigationController, ContainableController, self.displayNode.addSubnode(inCallStatusBar) } } - - let badgeNode = ASImageNode() - badgeNode.displaysAsynchronously = false - badgeNode.image = UIImage(bundleImageName: "Components/AppBadge") - self.badgeNode = badgeNode - self.displayNode.addSubnode(badgeNode) } - - private var badgeNode: ASImageNode? - + public func pushViewController(_ controller: ViewController) { self.pushViewController(controller, completion: {}) } diff --git a/submodules/Display/Source/Navigation/NavigationModalFrame.swift b/submodules/Display/Source/Navigation/NavigationModalFrame.swift index a4e36ecda3..c1f919be46 100644 --- a/submodules/Display/Source/Navigation/NavigationModalFrame.swift +++ b/submodules/Display/Source/Navigation/NavigationModalFrame.swift @@ -34,7 +34,7 @@ private func generateCornerImage(radius: CGFloat, type: CornerType) -> UIImage? }) } -final class NavigationModalFrame: ASDisplayNode { +public final class NavigationModalFrame: ASDisplayNode { private let topShade: ASDisplayNode private let leftShade: ASDisplayNode private let rightShade: ASDisplayNode @@ -50,7 +50,7 @@ final class NavigationModalFrame: ASDisplayNode { private var additionalProgress: CGFloat = 0.0 private var validLayout: ContainerViewLayout? - init(theme: NavigationControllerTheme) { + override public init() { self.topShade = ASDisplayNode() self.topShade.backgroundColor = .black self.leftShade = ASDisplayNode() @@ -81,13 +81,13 @@ final class NavigationModalFrame: ASDisplayNode { self.addSubnode(self.bottomRightCorner) } - func update(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + public func update(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { self.validLayout = layout self.updateShades(layout: layout, progress: 1.0 - self.progress, additionalProgress: self.additionalProgress, transition: transition, completion: {}) } - func updateDismissal(transition: ContainedViewLayoutTransition, progress: CGFloat, additionalProgress: CGFloat, completion: @escaping () -> Void) { + public func updateDismissal(transition: ContainedViewLayoutTransition, progress: CGFloat, additionalProgress: CGFloat, completion: @escaping () -> Void) { self.progress = progress self.additionalProgress = additionalProgress diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 99bfdc5ac8..fdbe56e465 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -12,7 +12,7 @@ open class SparseNode: ASDisplayNode { if !self.bounds.contains(point) { return nil } - for view in self.view.subviews { + for view in self.view.subviews.reversed() { if let result = view.hitTest(self.view.convert(point, to: view), with: event), result.isUserInteractionEnabled { return result } @@ -27,6 +27,26 @@ open class SparseNode: ASDisplayNode { } } +open class SparseContainerView: UIView { + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.alpha.isZero { + return nil + } + for view in self.subviews.reversed() { + if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled { + return result + } + } + + let result = super.hitTest(point, with: event) + if result != self { + return result + } else { + return nil + } + } +} + public final class NavigationBarTheme { public static func generateBackArrowImage(color: UIColor) -> UIImage? { return generateImage(CGSize(width: 13.0, height: 22.0), rotatedContext: { size, context in @@ -223,7 +243,7 @@ public final class NavigationBackgroundNode: ASDisplayNode { self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur) } - public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition) { + public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition, beginWithCurrentState: Bool = true) { self.validLayout = (size, cornerRadius) let contentFrame = CGRect(origin: CGPoint(), size: size) @@ -266,6 +286,150 @@ public final class NavigationBackgroundNode: ASDisplayNode { } } +open class BlurredBackgroundView: UIView { + private var _color: UIColor? + + private var enableBlur: Bool + + private var effectView: UIVisualEffectView? + private let backgroundView: UIView + + private var validLayout: (CGSize, CGFloat)? + + public var backgroundCornerRadius: CGFloat { + if let (_, cornerRadius) = self.validLayout { + return cornerRadius + } else { + return 0.0 + } + } + + public init(color: UIColor?, enableBlur: Bool = true) { + self._color = nil + self.enableBlur = enableBlur + + self.backgroundView = UIView() + + super.init(frame: CGRect()) + + self.addSubview(self.backgroundView) + + if let color = color { + self.updateColor(color: color, transition: .immediate) + } + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func updateBackgroundBlur(forceKeepBlur: Bool) { + if let color = self._color, self.enableBlur && !sharedIsReduceTransparencyEnabled && ((color.alpha > .ulpOfOne && color.alpha < 0.95) || forceKeepBlur) { + if self.effectView == nil { + let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) + //effectView.isHidden = true + + for subview in effectView.subviews { + if subview.description.contains("VisualEffectSubview") { + subview.isHidden = true + } + } + + if let sublayer = effectView.layer.sublayers?[0], let filters = sublayer.filters { + sublayer.backgroundColor = nil + sublayer.isOpaque = false + //sublayer.setValue(true as NSNumber, forKey: "allowsInPlaceFiltering") + let allowedKeys: [String] = [ + "colorSaturate", + "gaussianBlur" + ] + sublayer.filters = filters.filter { filter in + guard let filter = filter as? NSObject else { + return true + } + let filterName = String(describing: filter) + if !allowedKeys.contains(filterName) { + return false + } + return true + } + } + + if let (size, cornerRadius) = self.validLayout { + effectView.frame = CGRect(origin: CGPoint(), size: size) + ContainedViewLayoutTransition.immediate.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius) + effectView.clipsToBounds = !cornerRadius.isZero + } + self.effectView = effectView + self.insertSubview(effectView, at: 0) + } + } else if let effectView = self.effectView { + self.effectView = nil + effectView.removeFromSuperview() + } + } + + public func updateColor(color: UIColor, enableBlur: Bool? = nil, forceKeepBlur: Bool = false, transition: ContainedViewLayoutTransition) { + let effectiveEnableBlur = enableBlur ?? self.enableBlur + + if self._color == color && self.enableBlur == effectiveEnableBlur { + return + } + self._color = color + self.enableBlur = effectiveEnableBlur + + if sharedIsReduceTransparencyEnabled { + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color.withAlphaComponent(1.0)) + } else { + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color) + } + + self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur) + } + + public func update(size: CGSize, cornerRadius: CGFloat = 0.0, transition: ContainedViewLayoutTransition) { + self.validLayout = (size, cornerRadius) + + let contentFrame = CGRect(origin: CGPoint(), size: size) + transition.updateFrame(view: self.backgroundView, frame: contentFrame, beginWithCurrentState: true) + if let effectView = self.effectView, effectView.frame != contentFrame { + transition.updateFrame(layer: effectView.layer, frame: contentFrame, beginWithCurrentState: true) + if let sublayers = effectView.layer.sublayers { + for sublayer in sublayers { + transition.updateFrame(layer: sublayer, frame: contentFrame, beginWithCurrentState: true) + } + } + } + + transition.updateCornerRadius(layer: self.backgroundView.layer, cornerRadius: cornerRadius) + if let effectView = self.effectView { + transition.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius) + effectView.clipsToBounds = !cornerRadius.isZero + } + } + + public func update(size: CGSize, cornerRadius: CGFloat = 0.0, animator: ControlledTransitionAnimator) { + self.validLayout = (size, cornerRadius) + + let contentFrame = CGRect(origin: CGPoint(), size: size) + animator.updateFrame(layer: self.backgroundView.layer, frame: contentFrame, completion: nil) + if let effectView = self.effectView, effectView.frame != contentFrame { + animator.updateFrame(layer: effectView.layer, frame: contentFrame, completion: nil) + if let sublayers = effectView.layer.sublayers { + for sublayer in sublayers { + animator.updateFrame(layer: sublayer, frame: contentFrame, completion: nil) + } + } + } + + animator.updateCornerRadius(layer: self.backgroundView.layer, cornerRadius: cornerRadius, completion: nil) + if let effectView = self.effectView { + animator.updateCornerRadius(layer: effectView.layer, cornerRadius: cornerRadius, completion: nil) + effectView.clipsToBounds = !cornerRadius.isZero + } + } +} + open class NavigationBar: ASDisplayNode { public static var defaultSecondaryContentHeight: CGFloat { return 38.0 diff --git a/submodules/Display/Source/PortalView.swift b/submodules/Display/Source/PortalView.swift index aa8c401fed..d5a58cb6c6 100644 --- a/submodules/Display/Source/PortalView.swift +++ b/submodules/Display/Source/PortalView.swift @@ -16,6 +16,8 @@ public class PortalView { if let portalSuperview = self.view.superview, let index = portalSuperview.subviews.firstIndex(of: self.view) { portalSuperview.insertSubview(self.view, at: index) + } else if let portalSuperlayer = self.view.layer.superlayer, let index = portalSuperlayer.sublayers?.firstIndex(of: self.view.layer) { + portalSuperlayer.insertSublayer(self.view.layer, at: UInt32(index)) } } } diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index a5b9e8c6bc..1e318d6804 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -147,8 +147,26 @@ public final class TextNodeLayoutArguments { public let textShadowColor: UIColor? public let textStroke: (UIColor, CGFloat)? public let displaySpoilers: Bool + public let displayEmbeddedItemsUnderSpoilers: Bool - public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, verticalAlignment: TextVerticalAlignment = .top, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil, displaySpoilers: Bool = false) { + public init( + attributedString: NSAttributedString?, + backgroundColor: UIColor? = nil, + minimumNumberOfLines: Int = 0, + maximumNumberOfLines: Int, + truncationType: CTLineTruncationType, + constrainedSize: CGSize, + alignment: NSTextAlignment = .natural, + verticalAlignment: TextVerticalAlignment = .top, + lineSpacing: CGFloat = 0.12, + cutout: TextNodeCutout? = nil, + insets: UIEdgeInsets = UIEdgeInsets(), + lineColor: UIColor? = nil, + textShadowColor: UIColor? = nil, + textStroke: (UIColor, CGFloat)? = nil, + displaySpoilers: Bool = false, + displayEmbeddedItemsUnderSpoilers: Bool = false + ) { self.attributedString = attributedString self.backgroundColor = backgroundColor self.minimumNumberOfLines = minimumNumberOfLines @@ -164,6 +182,28 @@ public final class TextNodeLayoutArguments { self.textShadowColor = textShadowColor self.textStroke = textStroke self.displaySpoilers = displaySpoilers + self.displayEmbeddedItemsUnderSpoilers = displayEmbeddedItemsUnderSpoilers + } + + public func withAttributedString(_ attributedString: NSAttributedString?) -> TextNodeLayoutArguments { + return TextNodeLayoutArguments( + attributedString: attributedString, + backgroundColor: self.backgroundColor, + minimumNumberOfLines: self.minimumNumberOfLines, + maximumNumberOfLines: self.maximumNumberOfLines, + truncationType: self.truncationType, + constrainedSize: self.constrainedSize, + alignment: self.alignment, + verticalAlignment: self.verticalAlignment, + lineSpacing: self.lineSpacing, + cutout: self.cutout, + insets: self.insets, + lineColor: self.lineColor, + textShadowColor: self.textShadowColor, + textStroke: self.textStroke, + displaySpoilers: self.displaySpoilers, + displayEmbeddedItemsUnderSpoilers: self.displayEmbeddedItemsUnderSpoilers + ) } } @@ -881,7 +921,7 @@ public final class TextAccessibilityOverlayNode: ASDisplayNode { } } -public class TextNode: ASDisplayNode { +open class TextNode: ASDisplayNode { public internal(set) var cachedLayout: TextNodeLayout? override public init() { @@ -892,7 +932,7 @@ public class TextNode: ASDisplayNode { self.clipsToBounds = false } - override public func didLoad() { + override open func didLoad() { super.didLoad() } @@ -936,7 +976,7 @@ public class TextNode: ASDisplayNode { } } - static func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool) -> TextNodeLayout { + static func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool, displayEmbeddedItemsUnderSpoilers: Bool) -> TextNodeLayout { if let attributedString = attributedString { let stringLength = attributedString.length @@ -1139,7 +1179,7 @@ public class TextNode: ASDisplayNode { for run in runs { let runAttributes: NSDictionary = CTRunGetAttributes(run) if let _ = runAttributes["CTForegroundColorFromContext"] { - brokenLineRange.length = CTRunGetStringRange(run).location + brokenLineRange.length = CTRunGetStringRange(run).location - brokenLineRange.location break } } @@ -1181,12 +1221,6 @@ public class TextNode: ASDisplayNode { } addSpoiler(line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) - } else if let embeddedItem = (attributes[NSAttributedString.Key(rawValue: "TelegramEmbeddedItem")] as? AnyHashable ?? attributes[NSAttributedString.Key(rawValue: "Attribute__EmbeddedItem")] as? AnyHashable) { - var ascent: CGFloat = 0.0 - var descent: CGFloat = 0.0 - CTLineGetTypographicBounds(coreTextLine, &ascent, &descent, nil) - - addEmbeddedItem(item: embeddedItem, line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) } else if let _ = attributes[NSAttributedString.Key.strikethroughStyle] { let lowerX = floor(CTLineGetOffsetForStringIndex(coreTextLine, range.location, nil)) let upperX = ceil(CTLineGetOffsetForStringIndex(coreTextLine, range.location + range.length, nil)) @@ -1195,6 +1229,16 @@ public class TextNode: ASDisplayNode { } else if let paragraphStyle = attributes[NSAttributedString.Key.paragraphStyle] as? NSParagraphStyle { headIndent = paragraphStyle.headIndent } + + if let embeddedItem = (attributes[NSAttributedString.Key(rawValue: "TelegramEmbeddedItem")] as? AnyHashable ?? attributes[NSAttributedString.Key(rawValue: "Attribute__EmbeddedItem")] as? AnyHashable) { + if displayEmbeddedItemsUnderSpoilers || (attributes[NSAttributedString.Key(rawValue: "TelegramSpoiler")] == nil && attributes[NSAttributedString.Key(rawValue: "Attribute__Spoiler")] == nil) { + var ascent: CGFloat = 0.0 + var descent: CGFloat = 0.0 + CTLineGetTypographicBounds(coreTextLine, &ascent, &descent, nil) + + addEmbeddedItem(item: embeddedItem, line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) + } + } } } @@ -1268,12 +1312,6 @@ public class TextNode: ASDisplayNode { } addSpoiler(line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) - } else if let embeddedItem = (attributes[NSAttributedString.Key(rawValue: "TelegramEmbeddedItem")] as? AnyHashable ?? attributes[NSAttributedString.Key(rawValue: "Attribute__EmbeddedItem")] as? AnyHashable) { - var ascent: CGFloat = 0.0 - var descent: CGFloat = 0.0 - CTLineGetTypographicBounds(coreTextLine, &ascent, &descent, nil) - - addEmbeddedItem(item: embeddedItem, line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) } else if let _ = attributes[NSAttributedString.Key.strikethroughStyle] { let lowerX = floor(CTLineGetOffsetForStringIndex(coreTextLine, range.location, nil)) let upperX = ceil(CTLineGetOffsetForStringIndex(coreTextLine, range.location + range.length, nil)) @@ -1282,6 +1320,16 @@ public class TextNode: ASDisplayNode { } else if let paragraphStyle = attributes[NSAttributedString.Key.paragraphStyle] as? NSParagraphStyle { headIndent = paragraphStyle.headIndent } + + if let embeddedItem = (attributes[NSAttributedString.Key(rawValue: "TelegramEmbeddedItem")] as? AnyHashable ?? attributes[NSAttributedString.Key(rawValue: "Attribute__EmbeddedItem")] as? AnyHashable) { + if displayEmbeddedItemsUnderSpoilers || (attributes[NSAttributedString.Key(rawValue: "TelegramSpoiler")] == nil && attributes[NSAttributedString.Key(rawValue: "Attribute__Spoiler")] == nil) { + var ascent: CGFloat = 0.0 + var descent: CGFloat = 0.0 + CTLineGetTypographicBounds(coreTextLine, &ascent, &descent, nil) + + addEmbeddedItem(item: embeddedItem, line: coreTextLine, ascent: ascent, descent: descent, startIndex: range.location, endIndex: range.location + range.length) + } + } } let lineWidth = ceil(CGFloat(CTLineGetTypographicBounds(coreTextLine, nil, nil, nil) - CTLineGetTrailingWhitespaceWidth(coreTextLine))) @@ -1435,6 +1483,10 @@ public class TextNode: ASDisplayNode { for run in glyphRuns { let run = run as! CTRun let glyphCount = CTRunGetGlyphCount(run) + let attributes = CTRunGetAttributes(run) as NSDictionary + if attributes["Attribute__EmbeddedItem"] != nil { + continue + } CTRunDraw(run, context, CFRangeMake(0, glyphCount)) } } @@ -1539,11 +1591,11 @@ public class TextNode: ASDisplayNode { if stringMatch { layout = existingLayout } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers, displayEmbeddedItemsUnderSpoilers: arguments.displayEmbeddedItemsUnderSpoilers) updated = true } } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers, displayEmbeddedItemsUnderSpoilers: arguments.displayEmbeddedItemsUnderSpoilers) updated = true } @@ -2184,11 +2236,11 @@ open class TextView: UIView { if stringMatch { layout = existingLayout } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers, displayEmbeddedItemsUnderSpoilers: arguments.displayEmbeddedItemsUnderSpoilers) updated = true } } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke, displaySpoilers: arguments.displaySpoilers, displayEmbeddedItemsUnderSpoilers: arguments.displayEmbeddedItemsUnderSpoilers) updated = true } diff --git a/submodules/Display/Source/TooltipController.swift b/submodules/Display/Source/TooltipController.swift index c9ee3dcf3a..1ab86d59ef 100644 --- a/submodules/Display/Source/TooltipController.swift +++ b/submodules/Display/Source/TooltipController.swift @@ -122,12 +122,14 @@ open class TooltipController: ViewController, StandalonePresentableController { private let dismissImmediatelyOnLayoutUpdate: Bool private var timeoutTimer: SwiftSignalKit.Timer? + private var padding: CGFloat + private var layout: ContainerViewLayout? private var initialArrowOnBottom: Bool public var dismissed: ((Bool) -> Void)? - public init(content: TooltipControllerContent, baseFontSize: CGFloat, timeout: Double = 2.0, dismissByTapOutside: Bool = false, dismissByTapOutsideSource: Bool = false, dismissImmediatelyOnLayoutUpdate: Bool = false, arrowOnBottom: Bool = true) { + public init(content: TooltipControllerContent, baseFontSize: CGFloat, timeout: Double = 2.0, dismissByTapOutside: Bool = false, dismissByTapOutsideSource: Bool = false, dismissImmediatelyOnLayoutUpdate: Bool = false, arrowOnBottom: Bool = true, padding: CGFloat = 8.0) { self.content = content self.baseFontSize = baseFontSize self.timeout = timeout @@ -135,6 +137,7 @@ open class TooltipController: ViewController, StandalonePresentableController { self.dismissByTapOutsideSource = dismissByTapOutsideSource self.dismissImmediatelyOnLayoutUpdate = dismissImmediatelyOnLayoutUpdate self.initialArrowOnBottom = arrowOnBottom + self.padding = padding super.init(navigationBarPresentationData: nil) @@ -153,6 +156,7 @@ open class TooltipController: ViewController, StandalonePresentableController { self.displayNode = TooltipControllerNode(content: self.content, baseFontSize: self.baseFontSize, dismiss: { [weak self] tappedInside in self?.dismiss(tappedInside: tappedInside) }, dismissByTapOutside: self.dismissByTapOutside, dismissByTapOutsideSource: self.dismissByTapOutsideSource) + self.controllerNode.padding = self.padding self.controllerNode.arrowOnBottom = self.initialArrowOnBottom self.displayNodeDidLoad() } diff --git a/submodules/Display/Source/TooltipControllerNode.swift b/submodules/Display/Source/TooltipControllerNode.swift index e67cc95e79..d044cbc5f6 100644 --- a/submodules/Display/Source/TooltipControllerNode.swift +++ b/submodules/Display/Source/TooltipControllerNode.swift @@ -19,6 +19,8 @@ final class TooltipControllerNode: ASDisplayNode { var sourceRect: CGRect? var arrowOnBottom: Bool = true + var padding: CGFloat = 8.0 + private var dismissedByTouchOutside = false private var dismissByTapOutsideSource = false @@ -122,7 +124,7 @@ final class TooltipControllerNode: ASDisplayNode { } self.arrowOnBottom = arrowOnBottom - let horizontalOrigin: CGFloat = floor(min(max(8.0, sourceRect.midX - contentSize.width / 2.0), layout.size.width - contentSize.width - 8.0)) + let horizontalOrigin: CGFloat = floor(min(max(self.padding, sourceRect.midX - contentSize.width / 2.0), layout.size.width - contentSize.width - self.padding)) transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(x: horizontalOrigin, y: verticalOrigin), size: contentSize)) self.containerNode.relativeArrowPosition = (sourceRect.midX - horizontalOrigin, arrowOnBottom) diff --git a/submodules/Display/Source/UIKitUtils.swift b/submodules/Display/Source/UIKitUtils.swift index 2b6ee6a68e..5c6021eb33 100644 --- a/submodules/Display/Source/UIKitUtils.swift +++ b/submodules/Display/Source/UIKitUtils.swift @@ -387,7 +387,7 @@ public func assertNotOnMainThread(_ file: String = #file, line: Int = #line) { } public extension UIImage { - func precomposed() -> UIImage { + func precomposed() -> UIImage { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) self.draw(at: CGPoint()) let result = UIGraphicsGetImageFromCurrentImageContext()! @@ -483,6 +483,38 @@ private func makeLayerSubtreeSnapshot(layer: CALayer) -> CALayer? { return view } +private func makeLayerSubtreeSnapshotAsView(layer: CALayer) -> UIView? { + if layer is AVSampleBufferDisplayLayer { + return nil + } + let view = UIView() + view.layer.isHidden = layer.isHidden + view.layer.opacity = layer.opacity + view.layer.contents = layer.contents + view.layer.contentsRect = layer.contentsRect + view.layer.contentsScale = layer.contentsScale + view.layer.contentsCenter = layer.contentsCenter + view.layer.contentsGravity = layer.contentsGravity + view.layer.masksToBounds = layer.masksToBounds + view.layer.cornerRadius = layer.cornerRadius + view.layer.backgroundColor = layer.backgroundColor + if let sublayers = layer.sublayers { + for sublayer in sublayers { + let subtree = makeLayerSubtreeSnapshotAsView(layer: sublayer) + if let subtree = subtree { + subtree.layer.transform = sublayer.transform + subtree.layer.frame = sublayer.frame + subtree.layer.bounds = sublayer.bounds + view.addSubview(subtree) + } else { + return nil + } + } + } + return view +} + + public extension UIView { func snapshotContentTree(unhide: Bool = false, keepTransform: Bool = false) -> UIView? { let wasHidden = self.isHidden @@ -523,6 +555,26 @@ public extension CALayer { } } +public extension CALayer { + func snapshotContentTreeAsView(unhide: Bool = false) -> UIView? { + let wasHidden = self.isHidden + if unhide && wasHidden { + self.isHidden = false + } + let snapshot = makeLayerSubtreeSnapshotAsView(layer: self) + if unhide && wasHidden { + self.isHidden = true + } + if let snapshot = snapshot { + snapshot.frame = self.frame + snapshot.bounds = self.bounds + return snapshot + } + + return nil + } +} + public extension CGRect { var topLeft: CGPoint { return self.origin diff --git a/submodules/Display/Source/WindowContent.swift b/submodules/Display/Source/WindowContent.swift index 82b0b44a1c..37a8544460 100644 --- a/submodules/Display/Source/WindowContent.swift +++ b/submodules/Display/Source/WindowContent.swift @@ -240,6 +240,7 @@ public final class WindowKeyboardGestureRecognizerDelegate: NSObject, UIGestureR public class Window1 { public let hostView: WindowHostView + public let badgeView: UIImageView private var deviceMetrics: DeviceMetrics @@ -328,6 +329,10 @@ public class Window1 { public init(hostView: WindowHostView, statusBarHost: StatusBarHost?) { self.hostView = hostView + self.badgeView = UIImageView() + self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge") + self.badgeView.isHidden = true + self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle let boundsSize = self.hostView.eventView.bounds.size @@ -626,8 +631,9 @@ public class Window1 { } self.windowPanRecognizer = recognizer self.hostView.containerView.addGestureRecognizer(recognizer) + self.hostView.containerView.addSubview(self.badgeView) } - + public required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -650,6 +656,26 @@ public class Window1 { } } + private var forceBadgeHidden = true + public func setForceBadgeHidden(_ hidden: Bool) { + guard hidden != self.forceBadgeHidden else { + return + } + self.forceBadgeHidden = hidden + self.updateBadgeVisibility(layout: self.windowLayout) + } + + private func updateBadgeVisibility(layout: WindowLayout) { + let badgeIsHidden = !self.deviceMetrics.hasTopNotch || self.forceBadgeHidden || layout.size.width > layout.size.height + if badgeIsHidden != self.badgeView.isHidden && !badgeIsHidden { + Queue.mainQueue().after(0.3) { + self.badgeView.isHidden = badgeIsHidden + } + } else { + self.badgeView.isHidden = badgeIsHidden + } + } + public func setForceInCallStatusBar(_ forceInCallStatusBarText: String?, transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .easeInOut)) { if self.forceInCallStatusBarText != forceInCallStatusBarText { self.forceInCallStatusBarText = forceInCallStatusBarText @@ -828,7 +854,7 @@ public class Window1 { if let coveringView = self.coveringView { self.hostView.containerView.insertSubview(controller.view, belowSubview: coveringView) } else { - self.hostView.containerView.addSubview(controller.view) + self.hostView.containerView.insertSubview(controller.view, belowSubview: self.badgeView) } if let controller = controller as? ViewController { @@ -868,7 +894,7 @@ public class Window1 { if let controller = self.topPresentationContext.controllers.first { self.hostView.containerView.insertSubview(coveringView, belowSubview: controller.0.displayNode.view) } else { - self.hostView.containerView.addSubview(coveringView) + self.hostView.containerView.insertSubview(coveringView, belowSubview: self.badgeView) } if !self.windowLayout.size.width.isZero { coveringView.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size) @@ -1087,6 +1113,11 @@ public class Window1 { coveringView.frame = CGRect(origin: CGPoint(), size: self.windowLayout.size) coveringView.updateLayout(self.windowLayout.size) } + + if let image = self.badgeView.image { + self.updateBadgeVisibility(layout: self.windowLayout) + self.badgeView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.windowLayout.size.width - image.size.width) / 2.0), y: 6.0), size: image.size) + } } } } diff --git a/submodules/Emoji/Sources/EmojiUtils.swift b/submodules/Emoji/Sources/EmojiUtils.swift index 58ba322f87..fd58bb060f 100644 --- a/submodules/Emoji/Sources/EmojiUtils.swift +++ b/submodules/Emoji/Sources/EmojiUtils.swift @@ -5,7 +5,7 @@ import AVFoundation public extension UnicodeScalar { var isEmoji: Bool { switch self.value { - case 0x1F600...0x1F64F, 0x1F300...0x1F5FF, 0x1F680...0x1F6FF, 0x1F1E6...0x1F1FF, 0xE0020...0xE007F, 0xFE00...0xFE0F, 0x1F900...0x1F9FF, 0x1F018...0x1F0F5, 0x1F200...0x1F270, 65024...65039, 9100...9300, 8400...8447, 0x1F004, 0x1F18E, 0x1F191...0x1F19A, 0x1F5E8, 0x1FA70...0x1FA73, 0x1FA78...0x1FA7A, 0x1FA80...0x1FA82, 0x1FA90...0x1FA95: + case 0x1F600...0x1F64F, 0x1F300...0x1F5FF, 0x1F680...0x1F6FF, 0x1F1E6...0x1F1FF, 0xE0020...0xE007F, 0xFE00...0xFE0F, 0x1F900...0x1F9FF, 0x1F018...0x1F0F5, 0x1F200...0x1F270, 65024...65039, 9100...9300, 8400...8447, 0x1F004, 0x1F18E, 0x1F191...0x1F19A, 0x1F5E8, 0x1FA70...0x1FA73, 0x1FA78...0x1FA7A, 0x1FA80...0x1FA82, 0x1FA90...0x1FA95, 0x1F382: return true case 0x2603, 0x265F, 0x267E, 0x2692, 0x26C4, 0x26C8, 0x26CE, 0x26CF, 0x26D1...0x26D3, 0x26E9, 0x26F0...0x26F9, 0x2705, 0x270A, 0x270B, 0x2728, 0x274E, 0x2753...0x2755, 0x274C, 0x2795...0x2797, 0x27B0, 0x27BF: return true diff --git a/submodules/GalleryUI/BUILD b/submodules/GalleryUI/BUILD index c398c257d5..180d1e9a21 100644 --- a/submodules/GalleryUI/BUILD +++ b/submodules/GalleryUI/BUILD @@ -41,6 +41,9 @@ swift_library( "//submodules/InvisibleInkDustNode:InvisibleInkDustNode", "//submodules/TranslateUI:TranslateUI", "//submodules/Utils/RangeSet:RangeSet", + "//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", ], visibility = [ "//visibility:public", diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 2a85754ef1..8cb2ed0cf1 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -22,6 +22,9 @@ import UndoUI import ManagedAnimationNode import TelegramUniversalVideoContent import InvisibleInkDustNode +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white) private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionForward"), color: .white) @@ -133,10 +136,13 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll private let scrollWrapperNode: CaptionScrollWrapperNode private let scrollNode: ASScrollNode - private let textNode: ImmediateTextNode - private var spoilerTextNode: ImmediateTextNode? + private let textNode: ImmediateTextNodeWithEntities + private var spoilerTextNode: ImmediateTextNodeWithEntities? private var dustNode: InvisibleInkDustNode? + private let animationCache: AnimationCache + private let animationRenderer: MultiAnimationRenderer + private let authorNameNode: ASTextNode private let dateNode: ASTextNode private let backwardButton: PlaybackButtonNode @@ -319,7 +325,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.maskNode = ASDisplayNode() - self.textNode = ImmediateTextNode() + self.textNode = ImmediateTextNodeWithEntities() self.textNode.maximumNumberOfLines = 0 self.textNode.linkHighlightColor = UIColor(rgb: 0x5ac8fa, alpha: 0.2) @@ -350,6 +356,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self.statusNode = RadialStatusNode(backgroundNodeColor: .clear) self.statusNode.isUserInteractionEnabled = false + self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + self.animationRenderer = MultiAnimationRendererImpl() + super.init() self.addSubnode(self.contentNode) @@ -380,6 +391,15 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } } + self.textNode.arguments = TextNodeWithEntities.Arguments( + context: self.context, + cache: self.animationCache, + renderer: self.animationRenderer, + placeholderColor: defaultDarkPresentationTheme.list.mediaPlaceholderColor, + attemptSynchronous: false + ) + self.textNode.visibility = true + self.contentNode.view.addSubview(self.deleteButton) self.contentNode.view.addSubview(self.fullscreenButton) self.contentNode.view.addSubview(self.actionButton) @@ -684,7 +704,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll break } } - messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities) + messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities, message: message) } if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canFullscreen != !self.fullscreenButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { @@ -723,7 +743,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll private func updateSpoilers(textFrame: CGRect) { if let textLayout = self.textNode.cachedLayout, !textLayout.spoilers.isEmpty { if self.spoilerTextNode == nil { - let spoilerTextNode = ImmediateTextNode() + let spoilerTextNode = ImmediateTextNodeWithEntities() spoilerTextNode.attributedText = textNode.attributedText spoilerTextNode.maximumNumberOfLines = 0 spoilerTextNode.linkHighlightColor = UIColor(rgb: 0x5ac8fa, alpha: 0.2) @@ -1715,7 +1735,7 @@ private final class PlaybackButtonNode: HighlightTrackingButtonNode { self.textNode = ImmediateTextNode() self.textNode.attributedText = NSAttributedString(string: "15", font: Font.with(size: 11.0, design: .round, weight: .semibold, traits: []), textColor: .white) - super.init(pointerStyle: .circle) + super.init(pointerStyle: nil) self.addSubnode(self.backgroundIconNode) self.addSubnode(self.textNode) diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 55b307a474..37653494fa 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -131,8 +131,8 @@ private let italicFont = Font.italic(16.0) private let boldItalicFont = Font.semiboldItalic(16.0) private let fixedFont = UIFont(name: "Menlo-Regular", size: 15.0) ?? textFont -public func galleryCaptionStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> NSAttributedString { - return stringWithAppliedEntities(text, entities: entities, baseColor: .white, linkColor: UIColor(rgb: 0x5ac8fa), baseFont: textFont, linkFont: textFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: fixedFont, blockQuoteFont: textFont, underlineLinks: false) +public func galleryCaptionStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], message: Message?) -> NSAttributedString { + return stringWithAppliedEntities(text, entities: entities, baseColor: .white, linkColor: UIColor(rgb: 0x5ac8fa), baseFont: textFont, linkFont: textFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: fixedFont, blockQuoteFont: textFont, underlineLinks: false, message: message) } private func galleryMessageCaptionText(_ message: Message) -> String { @@ -176,7 +176,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese entities = result } - let caption = galleryCaptionStringWithAppliedEntities(text, entities: entities) + let caption = galleryCaptionStringWithAppliedEntities(text, entities: entities, message: message) return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: caption, displayInfoOnTop: displayInfoOnTop, hideControls: hideControls, fromPlayingVideo: fromPlayingVideo, isSecret: isSecret, landscape: landscape, timecode: timecode, playbackRate: playbackRate, configuration: configuration, playbackCompleted: playbackCompleted, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) } else { if let fileName = file.fileName, (fileName as NSString).pathExtension.lowercased() == "json" { @@ -224,7 +224,7 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese if let result = addLocallyGeneratedEntities(descriptionText, enabledTypes: [.timecode], entities: entities, mediaDuration: 86400) { entities = result } - description = galleryCaptionStringWithAppliedEntities(descriptionText, entities: entities) + description = galleryCaptionStringWithAppliedEntities(descriptionText, entities: entities, message: message) } return UniversalVideoGalleryItem(context: context, presentationData: presentationData, content: content, originData: GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp), indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) }, contentInfo: .message(message), caption: NSAttributedString(string: ""), description: description, displayInfoOnTop: displayInfoOnTop, fromPlayingVideo: fromPlayingVideo, isSecret: isSecret, landscape: landscape, timecode: timecode, playbackRate: playbackRate, configuration: configuration, performAction: performAction, openActionOptions: openActionOptions, storeMediaPlaybackState: storeMediaPlaybackState, present: present) } else { diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index edd50e3721..b146287009 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -474,20 +474,22 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { } let baseNavigationController = strongSelf.baseNavigationController() baseNavigationController?.view.endEditing(true) - let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in - let animateInAsReplacement = false - switch action { - case .add: - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - }), in: .window(.root)) - case let .remove(positionInList): - topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - }), in: .window(.root)) + let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { actions in + if let (info, items, action) = actions.first { + let animateInAsReplacement = false + switch action { + case .add: + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + }), in: .window(.root)) + case let .remove(positionInList): + topController?.present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + }), in: .window(.root)) + } } }) (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index dba478408d..66b2bbf180 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -147,10 +147,15 @@ private let moreButtonImage = generateTintedImage(image: UIImage(bundleImageName private let placeholderFont = Font.regular(16.0) private final class UniversalVideoGalleryItemPictureInPictureNode: ASDisplayNode { + enum Mode { + case pictureInPicture + case airplay + } + private let iconNode: ASImageNode private let textNode: ASTextNode - init(strings: PresentationStrings) { + init(strings: PresentationStrings, mode: Mode) { self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true self.iconNode.displayWithoutProcessing = true @@ -160,10 +165,20 @@ private final class UniversalVideoGalleryItemPictureInPictureNode: ASDisplayNode self.textNode = ASTextNode() self.textNode.isUserInteractionEnabled = false self.textNode.displaysAsynchronously = false - self.textNode.attributedText = NSAttributedString(string: strings.Embed_PlayingInPIP, font: placeholderFont, textColor: UIColor(rgb: 0x8e8e93)) + + let text: String + switch mode { + case .pictureInPicture: + text = strings.Embed_PlayingInPIP + case .airplay: + text = strings.Gallery_AirPlayPlaceholder + } + self.textNode.attributedText = NSAttributedString(string: text, font: placeholderFont, textColor: UIColor(rgb: 0x8e8e93)) super.init() + self.backgroundColor = UIColor(rgb: 0x333335) + self.addSubnode(self.iconNode) self.addSubnode(self.textNode) } @@ -975,7 +990,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if let pictureInPictureNode = self.pictureInPictureNode { if let item = self.item { - let placeholderSize = item.content.dimensions.fitted(layout.size) + var placeholderSize = item.content.dimensions.fitted(layout.size) + placeholderSize.height += 2.0 transition.updateFrame(node: pictureInPictureNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - placeholderSize.width) / 2.0), y: floor((layout.size.height - placeholderSize.height) / 2.0)), size: placeholderSize)) pictureInPictureNode.updateLayout(placeholderSize, transition: transition) } @@ -1144,11 +1160,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.videoNode = videoNode self.videoNodeUserInteractionEnabled = disablePlayerControls || forceEnableUserInteraction videoNode.isUserInteractionEnabled = disablePlayerControls || forceEnableUserInteraction - videoNode.backgroundColor = videoNode.ownsContentNode ? UIColor.black : UIColor(rgb: 0x333335) + videoNode.backgroundColor = UIColor.black if item.fromPlayingVideo { videoNode.canAttachContent = false } else { - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + self.updateDisplayPlaceholder() } scrubberView.setStatusSignal(videoNode.status |> map { value -> MediaPlayerStatus in @@ -1492,21 +1508,25 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.videoNode?.notifyPlaybackControlsHidden(!isVisible) } + private func updateDisplayPlaceholder() { + self.updateDisplayPlaceholder(!(self.videoNode?.ownsContentNode ?? true) || self.isAirPlayActive) + } + private func updateDisplayPlaceholder(_ displayPlaceholder: Bool) { if displayPlaceholder && !self.disablePictureInPicturePlaceholder { if self.pictureInPictureNode == nil { - let pictureInPictureNode = UniversalVideoGalleryItemPictureInPictureNode(strings: self.presentationData.strings) + let pictureInPictureNode = UniversalVideoGalleryItemPictureInPictureNode(strings: self.presentationData.strings, mode: self.isAirPlayActive ? .airplay : .pictureInPicture) pictureInPictureNode.isUserInteractionEnabled = false self.pictureInPictureNode = pictureInPictureNode self.insertSubnode(pictureInPictureNode, aboveSubnode: self.scrollNode) if let validLayout = self.validLayout { if let item = self.item { - let placeholderSize = item.content.dimensions.fitted(validLayout.0.size) - pictureInPictureNode.frame = CGRect(origin: CGPoint(x: floor((validLayout.0.size.width - placeholderSize.width) / 2.0), y: floor((validLayout.0.size.height - placeholderSize.height) / 2.0)), size: placeholderSize) + var placeholderSize = item.content.dimensions.fitted(validLayout.0.size) + placeholderSize.height += 2.0 + pictureInPictureNode.frame = CGRect(origin: CGPoint(x: floor((validLayout.0.size.width - placeholderSize.width) / 2.0), y: floorToScreenPixels((validLayout.0.size.height - placeholderSize.height) / 2.0)), size: placeholderSize) pictureInPictureNode.updateLayout(placeholderSize, transition: .immediate) } } - self.videoNode?.backgroundColor = UIColor(rgb: 0x333335) } } else if let pictureInPictureNode = self.pictureInPictureNode { self.pictureInPictureNode = nil @@ -1602,10 +1622,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else { videoNode.continuePlayingWithoutSound() } - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + self.updateDisplayPlaceholder() } else if !item.fromPlayingVideo { videoNode.canAttachContent = isVisible - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + self.updateDisplayPlaceholder() } if self.shouldAutoplayOnCentrality() { self.hideStatusNodeUntilCentrality = true @@ -1690,7 +1710,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { videoNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: videoNode.layer.transform), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25) videoNode.canAttachContent = true - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + self.updateDisplayPlaceholder() self.context.sharedContext.mediaManager.setOverlayVideoNode(nil) } else { @@ -1768,7 +1788,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { if self.item?.fromPlayingVideo ?? false { Queue.mainQueue().after(0.001) { videoNode.canAttachContent = true - self.updateDisplayPlaceholder(!videoNode.ownsContentNode) + self.updateDisplayPlaceholder() } } @@ -2456,6 +2476,16 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { c.setItems(strongSelf.contextMenuSpeedItems() |> map { ContextController.Items(content: .list($0)) }, minHeight: nil) }))) + +// if #available(iOS 11.0, *) { +// items.append(.action(ContextMenuActionItem(text: "AirPlay", textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/AirPlay"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in +// f(.default) +// guard let strongSelf = self else { +// return +// } +// strongSelf.beginAirPlaySetup() +// }))) +// } if let (message, _, _) = strongSelf.contentInfo() { for media in message.media { @@ -2578,43 +2608,67 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { return items } } + + private var isAirPlayActive = false + private var externalVideoPlayer: ExternalVideoPlayer? + func beginAirPlaySetup() { + guard let content = self.item?.content as? NativeVideoContent else { + return + } + if #available(iOS 11.0, *) { + self.externalVideoPlayer = ExternalVideoPlayer(context: self.context, content: content) + self.externalVideoPlayer?.openRouteSelection() + self.externalVideoPlayer?.isActiveUpdated = { [weak self] isActive in + if let strongSelf = self { + if strongSelf.isAirPlayActive && !isActive { + strongSelf.externalVideoPlayer = nil + } + strongSelf.isAirPlayActive = isActive + strongSelf.updateDisplayPlaceholder() + } + } + } + } @objc func openStickersButtonPressed() { - if let content = self.item?.content as? NativeVideoContent { - let context = self.context - let media = content.fileReference.abstract + guard let content = self.item?.content as? NativeVideoContent else { + return + } + let context = self.context + let media = content.fileReference.abstract - let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - let topController = (self.baseNavigationController()?.topViewController as? ViewController) - let progressSignal = Signal { subscriber in - let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) - topController?.present(controller, in: .window(.root), with: nil) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() - } + let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } + let topController = (self.baseNavigationController()?.topViewController as? ViewController) + let progressSignal = Signal { subscriber in + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + topController?.present(controller, in: .window(.root), with: nil) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() } } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - - self.isInteractingPromise.set(true) - - let signal = self.context.engine.stickers.stickerPacksAttachedToMedia(media: media) - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() - } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + self.isInteractingPromise.set(true) + + let signal = self.context.engine.stickers.stickerPacksAttachedToMedia(media: media) + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() } - let _ = (signal - |> deliverOnMainQueue).start(next: { [weak self] packs in - guard let strongSelf = self, !packs.isEmpty else { - return - } - let baseNavigationController = strongSelf.baseNavigationController() - baseNavigationController?.view.endEditing(true) - let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in + } + let _ = (signal + |> deliverOnMainQueue).start(next: { [weak self] packs in + guard let strongSelf = self, !packs.isEmpty else { + return + } + let baseNavigationController = strongSelf.baseNavigationController() + baseNavigationController?.view.endEditing(true) + let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: Array(packs.prefix(1)), sendSticker: nil, actionPerformed: { actions in + if let (info, items, action) = actions.first { let animateInAsReplacement = false switch action { case .add: @@ -2629,12 +2683,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { return true }), in: .window(.root)) } - }, dismissed: { [weak self] in - self?.isInteractingPromise.set(false) - }) - (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) + } + }, dismissed: { [weak self] in + self?.isInteractingPromise.set(false) }) - } + (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) + }) } override func adjustForPreviewing() { diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index ae3e247927..92e86ddaee 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -340,7 +340,7 @@ public final class SecretMediaPreviewController: ViewController { |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self, strongSelf.traceVisibility() { if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() } else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat { let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: strongSelf.messageId.peerId).start() } diff --git a/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift b/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift index 0c22d1e273..ae33e87612 100644 --- a/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift +++ b/submodules/GradientBackground/Sources/SoftwareGradientBackground.swift @@ -71,7 +71,7 @@ public func adjustSaturationInContext(context: DrawingContext, saturation: CGFlo vImageMatrixMultiply_ARGB8888(&buffer, &buffer, &matrix, divisor, nil, nil, vImage_Flags(kvImageDoNotTile)) } -private func generateGradient(size: CGSize, colors inputColors: [UIColor], positions: [CGPoint], adjustSaturation: CGFloat = 1.0) -> UIImage { +private func generateGradient(size: CGSize, colors inputColors: [UIColor], positions: [CGPoint], adjustSaturation: CGFloat = 1.0) -> (UIImage, String) { let colors: [UIColor] = inputColors.count == 1 ? [inputColors[0], inputColors[0], inputColors[0]] : inputColors let width = Int(size.width) @@ -179,7 +179,23 @@ private func generateGradient(size: CGSize, colors inputColors: [UIColor], posit adjustSaturationInContext(context: context, saturation: adjustSaturation) } - return context.generateImage()! + var hashString = "" + hashString.append("\(size.width)x\(size.height)") + for color in colors { + hashString.append("_\(color.argb)") + } + for position in positions { + hashString.append("_\(position.x):\(position.y)") + } + hashString.append("_\(adjustSaturation)") + + return (context.generateImage()!, hashString) +} + +public protocol GradientBackgroundPatternOverlayLayer: CALayer { + var isAnimating: Bool { get set } + + func updateCompositionData(size: CGSize, backgroundImage: UIImage, backgroundImageHash: String) } public final class GradientBackgroundNode: ASDisplayNode { @@ -218,11 +234,13 @@ public final class GradientBackgroundNode: ASDisplayNode { public static func generatePreview(size: CGSize, colors: [UIColor]) -> UIImage { let positions = gatherPositions(shiftArray(array: GradientBackgroundNode.basePositions, offset: 0)) - return generateGradient(size: size, colors: colors, positions: positions) + return generateGradient(size: size, colors: colors, positions: positions).0 } private var colors: [UIColor] private var phase: Int = 0 + + private var backgroundImageHash: String? public let contentView: UIImageView private var validPhase: Int? @@ -234,7 +252,7 @@ public final class GradientBackgroundNode: ASDisplayNode { if let current = self._dimmedImage { return current } else if let (size, colors, positions) = self.dimmedImageParams { - self._dimmedImage = generateGradient(size: size, colors: colors, positions: positions, adjustSaturation: self.saturation) + self._dimmedImage = generateGradient(size: size, colors: colors, positions: positions, adjustSaturation: self.saturation).0 return self._dimmedImage } else { return nil @@ -246,9 +264,13 @@ public final class GradientBackgroundNode: ASDisplayNode { private let useSharedAnimationPhase: Bool static var sharedPhase: Int = 0 + + private var isAnimating: Bool = false private let saturation: CGFloat + private var patternOverlayLayer: GradientBackgroundPatternOverlayLayer? + public init(colors: [UIColor]? = nil, useSharedAnimationPhase: Bool = false, adjustSaturation: Bool = true) { self.useSharedAnimationPhase = useSharedAnimationPhase self.saturation = adjustSaturation ? 1.7 : 1.0 @@ -274,6 +296,31 @@ public final class GradientBackgroundNode: ASDisplayNode { deinit { } + + public func setPatternOverlay(layer: GradientBackgroundPatternOverlayLayer?) { + if self.patternOverlayLayer === layer { + return + } + + if let patternOverlayLayer = self.patternOverlayLayer { + if patternOverlayLayer.superlayer == self.layer { + patternOverlayLayer.removeFromSuperlayer() + } + self.patternOverlayLayer = nil + } + + self.patternOverlayLayer = layer + + if let patternOverlayLayer = self.patternOverlayLayer { + self.layer.addSublayer(patternOverlayLayer) + + patternOverlayLayer.isAnimating = self.isAnimating + + if let image = self.contentView.image, let backgroundImageHash = self.backgroundImageHash, self.contentView.bounds.width > 1.0, self.contentView.bounds.height > 1.0 { + patternOverlayLayer.updateCompositionData(size: self.contentView.bounds.size, backgroundImage: image, backgroundImageHash: backgroundImageHash) + } + } + } public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition, extendAnimation: Bool, backwards: Bool, completion: @escaping () -> Void) { let sizeUpdated = self.validLayout != size @@ -283,6 +330,9 @@ public final class GradientBackgroundNode: ASDisplayNode { let positions = gatherPositions(shiftArray(array: GradientBackgroundNode.basePositions, offset: self.phase % 8)) + let previousImage = self.contentView.image + let previousSize = self.contentView.bounds.size + if let validPhase = self.validPhase { if validPhase != self.phase || self.invalidated { self.validPhase = self.phase @@ -318,7 +368,7 @@ public final class GradientBackgroundNode: ASDisplayNode { } if case let .animated(duration, curve) = transition, duration > 0.001 { - var images: [UIImage] = [] + var images: [(UIImage, String)] = [] var dimmedImages: [UIImage] = [] let needDimmedImages = !self.cloneNodes.isEmpty @@ -350,16 +400,17 @@ public final class GradientBackgroundNode: ASDisplayNode { images.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions)) if needDimmedImages { - dimmedImages.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions, adjustSaturation: self.saturation)) + dimmedImages.append(generateGradient(size: imageSize, colors: self.colors, positions: morphedPositions, adjustSaturation: self.saturation).0) } } self.dimmedImageParams = (imageSize, self.colors, gatherPositions(shiftArray(array: GradientBackgroundNode.basePositions, offset: self.phase % 8))) - self.contentView.image = images.last + self.contentView.image = images[images.count - 1].0 + self.backgroundImageHash = images[images.count - 1].1 let animation = CAKeyframeAnimation(keyPath: "contents") - animation.values = images.map { $0.cgImage! } + animation.values = images.map { $0.0.cgImage! } animation.duration = duration * UIView.animationDurationFactor() if backwards || extendAnimation { animation.calculationMode = .discrete @@ -372,7 +423,19 @@ public final class GradientBackgroundNode: ASDisplayNode { animation.beginTime = self.contentView.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.25 } - animation.completion = { _ in + + self.isAnimating = true + if let patternOverlayLayer = self.patternOverlayLayer { + patternOverlayLayer.isAnimating = true + } + animation.completion = { [weak self] value in + if let strongSelf = self, value { + strongSelf.isAnimating = false + if let patternOverlayLayer = strongSelf.patternOverlayLayer { + patternOverlayLayer.isAnimating = false + } + } + completion() } @@ -399,10 +462,11 @@ public final class GradientBackgroundNode: ASDisplayNode { } } } else { - let image = generateGradient(size: imageSize, colors: self.colors, positions: positions) + let (image, imageHash) = generateGradient(size: imageSize, colors: self.colors, positions: positions) self.contentView.image = image + self.backgroundImageHash = imageHash - let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation) + let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation).0 self._dimmedImage = dimmedImage self.dimmedImageParams = (imageSize, self.colors, positions) @@ -412,14 +476,30 @@ public final class GradientBackgroundNode: ASDisplayNode { completion() } + } else if sizeUpdated { + let (image, imageHash) = generateGradient(size: imageSize, colors: self.colors, positions: positions) + self.contentView.image = image + self.backgroundImageHash = imageHash + + let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation).0 + self.dimmedImageParams = (imageSize, self.colors, positions) + + for cloneNode in self.cloneNodes { + cloneNode.value?.image = dimmedImage + } + + self.validPhase = self.phase + + completion() } else { completion() } } else if sizeUpdated { - let image = generateGradient(size: imageSize, colors: self.colors, positions: positions) + let (image, imageHash) = generateGradient(size: imageSize, colors: self.colors, positions: positions) self.contentView.image = image + self.backgroundImageHash = imageHash - let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation) + let dimmedImage = generateGradient(size: imageSize, colors: self.colors, positions: positions, adjustSaturation: self.saturation).0 self.dimmedImageParams = (imageSize, self.colors, positions) for cloneNode in self.cloneNodes { @@ -434,6 +514,12 @@ public final class GradientBackgroundNode: ASDisplayNode { } transition.updateFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: size)) + + if self.contentView.image !== previousImage || self.contentView.bounds.size != previousSize { + if let patternOverlayLayer = self.patternOverlayLayer, let imageHash = self.backgroundImageHash, let image = self.contentView.image, self.contentView.bounds.width > 1.0, self.contentView.bounds.height > 1.0 { + patternOverlayLayer.updateCompositionData(size: size, backgroundImage: image, backgroundImageHash: imageHash) + } + } } public func updateColors(colors: [UIColor]) { diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index e34bd134e7..1fc0704580 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -47,7 +47,7 @@ public final class HashtagSearchController: TelegramBaseController { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) return result.messages.map({ .message(EngineMessage($0), EngineRenderedPeer(message: EngineMessage($0)), result.readStates[$0.id.peerId].flatMap(EnginePeerReadCounters.init), chatListPresentationData, result.totalCount, nil, false, .index($0.index), nil, .generic, false) }) } - let interaction = ChatListNodeInteraction(activateSearch: { + let interaction = ChatListNodeInteraction(context: context, activateSearch: { }, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 1bb571e473..163dadd050 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -240,7 +240,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.wrappingScrollNode.view.contentInsetAdjustmentBehavior = .never } - self.contentGridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>? in + self.contentGridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError>? in if let strongSelf = self { if let itemNode = strongSelf.contentGridNode.itemNodeAtPoint(point) as? StickerPackPreviewGridItemNode, let item = itemNode.stickerPackItem { var menuItems: [ContextMenuItem] = [] @@ -259,14 +259,14 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll } }))) } - return .single((itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, item: item, menu: menuItems))) + return .single((itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, item: item, menu: menuItems))) } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { - let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) controller.visibilityUpdated = { [weak self] visible in if let strongSelf = self { @@ -405,7 +405,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll } else { title = self.presentationData.strings.ImportStickerPack_StickerCount(Int32(self.currentItems.count)) } - self.contentTitleNode.attributedText = stringWithAppliedEntities(title, entities: [], baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont) + self.contentTitleNode.attributedText = stringWithAppliedEntities(title, entities: [], baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont, message: nil) if !forceTitleUpdate { transaction = StickerPackPreviewGridTransaction(previousList: previousItems, list: self.currentItems, account: self.context.account, interaction: self.interaction, theme: self.presentationData.theme) @@ -694,7 +694,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll } strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in if case .info = action { - (navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _, _, _ in + (navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _ in }), in: .window(.root)) } return true diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackTitleController.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackTitleController.swift index 9ffc1207f0..eced81ab2c 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackTitleController.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackTitleController.swift @@ -764,7 +764,7 @@ func importStickerPackTitleController(context: AccountContext, title: String, te controller.willDismiss = { [weak contentNode] in contentNode?.inputFieldNode.deactivateInput() } - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller, weak contentNode] animated in @@ -854,7 +854,7 @@ func importStickerPackShortNameController(context: AccountContext, title: String controller.willDismiss = { [weak contentNode] in contentNode?.inputFieldNode.deactivateInput() } - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller, weak contentNode] animated in diff --git a/submodules/ImportStickerPackUI/Sources/StickerPreviewPeekContent.swift b/submodules/ImportStickerPackUI/Sources/StickerPreviewPeekContent.swift index 9ce887618f..ed757880c8 100644 --- a/submodules/ImportStickerPackUI/Sources/StickerPreviewPeekContent.swift +++ b/submodules/ImportStickerPackUI/Sources/StickerPreviewPeekContent.swift @@ -64,6 +64,8 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController private var containerLayout: (ContainerViewLayout, CGFloat)? + private let _ready = Promise() + init(account: Account, item: ImportStickerPack.Sticker) { self.account = account self.item = item @@ -104,6 +106,21 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController } self.addSubnode(self.textNode) + + if let animationNode = self.animationNode { + animationNode.started = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf._ready.set(.single(true)) + } + } else { + self._ready.set(.single(true)) + } + } + + func ready() -> Signal { + return self._ready.get() } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { diff --git a/submodules/InAppPurchaseManager/BUILD b/submodules/InAppPurchaseManager/BUILD index ce210e161f..03bc8fd60e 100644 --- a/submodules/InAppPurchaseManager/BUILD +++ b/submodules/InAppPurchaseManager/BUILD @@ -13,6 +13,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", + "//submodules/TelegramStringFormatting:TelegramStringFormatting", ], visibility = [ "//visibility:public", diff --git a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift index 91eb0e8231..1e64af4ddc 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -4,21 +4,79 @@ import SwiftSignalKit import StoreKit import Postbox import TelegramCore +import TelegramStringFormatting + +private let productIdentifiers = [ + "org.telegram.telegramPremium.monthly", + "org.telegram.telegramPremium.twelveMonths", + "org.telegram.telegramPremium.sixMonths", + "org.telegram.telegramPremium.threeMonths" +] public final class InAppPurchaseManager: NSObject { - public final class Product { + public final class Product: Equatable { + private lazy var numberFormatter: NumberFormatter = { + let numberFormatter = NumberFormatter() + numberFormatter.numberStyle = .currency + numberFormatter.locale = self.skProduct.priceLocale + return numberFormatter + }() + let skProduct: SKProduct init(skProduct: SKProduct) { self.skProduct = skProduct } - public var price: String { - let numberFormatter = NumberFormatter() - numberFormatter.numberStyle = .currency - numberFormatter.locale = self.skProduct.priceLocale - return numberFormatter.string(from: self.skProduct.price) ?? "" + public var id: String { + return self.skProduct.productIdentifier } + + public var isSubscription: Bool { + if #available(iOS 12.0, *) { + return self.skProduct.subscriptionGroupIdentifier != nil + } else if #available(iOS 11.2, *) { + return self.skProduct.subscriptionPeriod != nil + } else { + return self.id.contains(".monthly") + } + } + + public var price: String { + return self.numberFormatter.string(from: self.skProduct.price) ?? "" + } + + public func pricePerMonth(_ monthsCount: Int) -> String { + let price = self.skProduct.price.dividing(by: NSDecimalNumber(value: monthsCount)) + return self.numberFormatter.string(from: price) ?? "" + } + + public var priceValue: NSDecimalNumber { + return self.skProduct.price + } + + public var priceCurrencyAndAmount: (currency: String, amount: Int64) { + if let currencyCode = self.numberFormatter.currencyCode, + let amount = fractionalToCurrencyAmount(value: self.priceValue.doubleValue, currency: currencyCode) { + return (currencyCode, amount) + } else { + return ("", 0) + } + } + + public static func ==(lhs: Product, rhs: Product) -> Bool { + if lhs.id != rhs.id { + return false + } + if lhs.isSubscription != rhs.isSubscription { + return false + } + if lhs.priceValue != rhs.priceValue { + return false + } + return true + } + } public enum PurchaseState { @@ -41,9 +99,11 @@ public final class InAppPurchaseManager: NSObject { private final class PaymentTransactionContext { var state: SKPaymentTransactionState? + var targetPeerId: PeerId? let subscriber: (TransactionState) -> Void - init(subscriber: @escaping (TransactionState) -> Void) { + init(targetPeerId: PeerId?, subscriber: @escaping (TransactionState) -> Void) { + self.targetPeerId = targetPeerId self.subscriber = subscriber } } @@ -58,7 +118,6 @@ public final class InAppPurchaseManager: NSObject { } private let engine: TelegramEngine - private let premiumProductId: String private var products: [Product] = [] private var productsPromise = Promise<[Product]>([]) @@ -71,10 +130,9 @@ public final class InAppPurchaseManager: NSObject { private let disposableSet = DisposableDict() - public init(engine: TelegramEngine, premiumProductId: String) { + public init(engine: TelegramEngine) { self.engine = engine - self.premiumProductId = premiumProductId - + super.init() SKPaymentQueue.default().add(self) @@ -90,11 +148,8 @@ public final class InAppPurchaseManager: NSObject { } private func requestProducts() { - guard !self.premiumProductId.isEmpty else { - return - } Logger.shared.log("InAppPurchaseManager", "Requesting products") - let productRequest = SKProductsRequest(productIdentifiers: Set([self.premiumProductId])) + let productRequest = SKProductsRequest(productIdentifiers: Set(productIdentifiers)) productRequest.delegate = self productRequest.start() @@ -126,10 +181,15 @@ public final class InAppPurchaseManager: NSObject { } } - public func buyProduct(_ product: Product) -> Signal { + public func buyProduct(_ product: Product, targetPeerId: PeerId? = nil) -> Signal { if !self.canMakePayments { return .fail(.cantMakePayments) } + + if !product.isSubscription && targetPeerId == nil { + return .fail(.cantMakePayments) + } + let accountPeerId = "\(self.engine.account.peerId.toInt64())" Logger.shared.log("InAppPurchaseManager", "Buying: account \(accountPeerId), product \(product.skProduct.productIdentifier), price \(product.price)") @@ -143,7 +203,7 @@ public final class InAppPurchaseManager: NSObject { let disposable = MetaDisposable() self.stateQueue.async { - let paymentContext = PaymentTransactionContext(subscriber: { state in + let paymentContext = PaymentTransactionContext(targetPeerId: targetPeerId, subscriber: { state in switch state { case let .purchased(transactionId), let .restored(transactionId): if let transactionId = transactionId { @@ -221,6 +281,9 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { self.stateQueue.async { let accountPeerId = "\(self.engine.account.peerId.toInt64())" + + let paymentContexts = self.paymentContexts + var transactionsToAssign: [SKPaymentTransaction] = [] for transaction in transactions { if let applicationUsername = transaction.payment.applicationUsername, applicationUsername != accountPeerId { @@ -263,8 +326,33 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { let transactionIds = transactionsToAssign.compactMap({ $0.transactionIdentifier }).joined(separator: ", ") Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), sending receipt for transactions [\(transactionIds)]") + let transaction = transactionsToAssign.first + let purposeSignal: Signal + if let productIdentifier = transaction?.payment.productIdentifier, let targetPeerId = paymentContexts[productIdentifier]?.targetPeerId { + purposeSignal = self.availableProducts + |> filter { products in + return !products.isEmpty + } + |> take(1) + |> map { products -> AppStoreTransactionPurpose in + if let product = products.first(where: { $0.id == productIdentifier }) { + let (currency, amount) = product.priceCurrencyAndAmount + return .gift(peerId: targetPeerId, currency: currency, amount: amount) + } else { + return .gift(peerId: targetPeerId, currency: "", amount: 0) + } + } + } else { + purposeSignal = .single(.subscription) + } + + let receiptData = getReceiptData() ?? Data() self.disposableSet.set( - self.engine.payments.sendAppStoreReceipt(receipt: getReceiptData() ?? Data(), restore: false).start(error: { [weak self] _ in + (purposeSignal + |> castError(AssignAppStoreTransactionError.self) + |> mapToSignal { purpose -> Signal in + self.engine.payments.sendAppStoreReceipt(receipt: receiptData, purpose: purpose) + }).start(error: { [weak self] _ in Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transactions [\(transactionIds)] failed to assign") for transaction in transactions { self?.stateQueue.async { @@ -294,7 +382,7 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { if let receiptData = getReceiptData() { self.disposableSet.set( - self.engine.payments.sendAppStoreReceipt(receipt: receiptData, restore: true).start(error: { error in + self.engine.payments.sendAppStoreReceipt(receipt: receiptData, purpose: .restore).start(error: { error in Queue.mainQueue().async { if case .serverProvided = error { onRestoreCompletion(.succeed(true)) diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 7cfb25ff52..8f73d257f9 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1365,7 +1365,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { }, showAll: false) let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let controller = LocationViewController(context: self.context, subject: message, params: controllerParams) self.pushController(controller) diff --git a/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift b/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift index 802d3c2760..ede2fdcd3a 100644 --- a/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift +++ b/submodules/ItemListAddressItem/Sources/ItemListAddressItem.swift @@ -197,7 +197,7 @@ public class ItemListAddressItemNode: ListViewItemNode { let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: labelFont, textColor: labelColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let baseColor = item.theme.list.itemPrimaryTextColor - let string = stringWithAppliedEntities(item.text, entities: [], baseColor: baseColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont) + let string = stringWithAppliedEntities(item.text, entities: [], baseColor: baseColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont, message: nil) let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset - 98.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let padding: CGFloat = !item.label.isEmpty ? 39.0 : 20.0 diff --git a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift index 0666a6d3f2..db88c1e006 100644 --- a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift +++ b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift @@ -768,12 +768,13 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { strongSelf.animationNode = animationNode strongSelf.addSubnode(animationNode) - animationNode.setup(source: AnimatedStickerResourceSource(account: item.account, resource: resource, isVideo: isVideo), width: 80, height: 80, playbackMode: .loop, mode: .cached) + animationNode.setup(source: AnimatedStickerResourceSource(account: item.account, resource: resource, isVideo: isVideo), width: 80, height: 80, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) } animationNode.visibility = strongSelf.visibility != .none && item.playAnimatedStickers animationNode.isHidden = !item.playAnimatedStickers strongSelf.imageNode.isHidden = item.playAnimatedStickers if let animationNode = strongSelf.animationNode { + animationNode.updateLayout(size: imageFrame.size) transition.updateFrame(node: animationNode, frame: imageFrame) } } diff --git a/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift index 0587122172..30ba660d9b 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift @@ -20,6 +20,7 @@ public enum ItemListDisclosureLabelStyle { case text case detailText case coloredText(UIColor) + case textWithIcon(UIImage) case multilineDetailText case badge(UIColor) case color(UIColor) @@ -235,7 +236,9 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode { updatedLabelImage = generateFilledCircleImage(diameter: 17.0, color: color) } } - if case let .image(image, _) = item.labelStyle { + if case let .textWithIcon(image) = item.labelStyle { + updatedLabelImage = generateTintedImage(image: image, color: item.presentationData.theme.list.itemSecondaryTextColor) + } else if case let .image(image, _) = item.labelStyle { updatedLabelImage = image } @@ -473,7 +476,18 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode { } strongSelf.labelNode.frame = labelFrame - if case let .image(_, size) = item.labelStyle { + if case .textWithIcon = item.labelStyle { + if let updatedLabelImage = updatedLabelImage { + strongSelf.labelImageNode.image = updatedLabelImage + } + if strongSelf.labelImageNode.supernode == nil { + strongSelf.addSubnode(strongSelf.labelImageNode) + } + + if let size = strongSelf.labelImageNode.image?.size { + strongSelf.labelImageNode.frame = CGRect(origin: CGPoint(x: labelFrame.minX - size.width - 5.0, y: floor((layout.contentSize.height - size.height) / 2.0) - 1.0), size: size) + } + } else if case let .image(_, size) = item.labelStyle { if let updatedLabelImage = updatedLabelImage { strongSelf.labelImageNode.image = updatedLabelImage } diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift index 4b1f135ecb..b2d1930fb7 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift @@ -197,7 +197,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { } let entities = generateTextEntities(item.text, enabledTypes: item.enabledEntityTypes) - let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont) + let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont, message: nil) let (titleLayout, titleApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) diff --git a/submodules/ItemListUI/Sources/Items/ItemListTextWithLabelItem.swift b/submodules/ItemListUI/Sources/Items/ItemListTextWithLabelItem.swift index b4767d0532..784d308dd7 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListTextWithLabelItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListTextWithLabelItem.swift @@ -215,7 +215,7 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode { case .highlighted: baseColor = item.presentationData.theme.list.itemHighlightedColor } - let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: baseColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont) + let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: baseColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont, message: nil) let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let contentSize = CGSize(width: params.width, height: textLayout.size.height + labelLayout.size.height + 22.0) diff --git a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift index bb935c0295..14159d8e10 100644 --- a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift +++ b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift @@ -178,7 +178,7 @@ final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollVi let animation = contentNode.layer.makeAnimation(from: 0.0 as NSNumber, to: 1.0 as NSNumber, keyPath: "opacity", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.25) animation.fillMode = .both if !fastOut { - animation.beginTime = CACurrentMediaTime() + 0.1 + animation.beginTime = contentNode.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.1 } contentNode.layer.add(animation, forKey: "opacity") diff --git a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift index 4e2d372bb9..eabbb8e37a 100644 --- a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift +++ b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift @@ -199,7 +199,7 @@ final class LanguageLinkPreviewControllerNode: ViewControllerTracingNode, UIScro let animation = contentNode.layer.makeAnimation(from: 0.0 as NSNumber, to: 1.0 as NSNumber, keyPath: "opacity", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.35) animation.fillMode = .both if !fastOut { - animation.beginTime = CACurrentMediaTime() + 0.1 + animation.beginTime = contentNode.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.1 } contentNode.layer.add(animation, forKey: "opacity") diff --git a/submodules/LegacyComponents/Sources/PGVideoMovie.m b/submodules/LegacyComponents/Sources/PGVideoMovie.m index 274ec0605c..ceb10a7b57 100755 --- a/submodules/LegacyComponents/Sources/PGVideoMovie.m +++ b/submodules/LegacyComponents/Sources/PGVideoMovie.m @@ -16,8 +16,8 @@ GLfloat kColorConversion601FullRangeDefault[] = { GLfloat kColorConversion709Default[] = { 1, 1, 1, - 0, -.21482, 2.12798, - 1.28033, -.38059, 0, + 0, -0.1873, 1.8556, + 1.5748, -0.4681, 0, }; GLfloat *kColorConversion601 = kColorConversion601Default; diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift index 1c6c2f3346..ed309b3018 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyMediaPickers.swift @@ -347,7 +347,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId: fileAttributes.append(.Animated) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes) - subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) + subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) subscriber.putCompletion() } else { subscriber.putError(Void()) @@ -389,7 +389,7 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationI fileAttributes.append(.Animated) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes) - subscriber.putNext(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) + subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId)) subscriber.putCompletion() } else { subscriber.putError(Void()) @@ -463,7 +463,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) } } case let .asset(asset): @@ -486,7 +486,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: false)) case .tempFile: break } @@ -516,7 +516,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) case let .asset(asset): var randomId: Int64 = 0 arc4random_buf(&randomId, 8) @@ -530,7 +530,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: true)) default: break } @@ -665,7 +665,7 @@ public func legacyAssetPickerEnqueueMessages(account: Account, signals: [Any]) - attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: asFile)) + messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil), uniqueId: item.uniqueId, isFile: asFile)) } } } diff --git a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift index e5aecb7f92..131e2b51fb 100644 --- a/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageSnippetItemNode.swift @@ -386,6 +386,10 @@ public final class ListMessageSnippetItemNode: ListMessageNode { title = NSAttributedString(string: urlString, font: titleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor) iconText = NSAttributedString(string: "S", font: iconFont, textColor: UIColor.white) + } else if url.path.hasPrefix("/addemoji/") { + title = NSAttributedString(string: urlString, font: titleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor) + + iconText = NSAttributedString(string: "E", font: iconFont, textColor: UIColor.white) } else { iconText = NSAttributedString(string: host[.. Int { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) return wrappedWrite(self.fd, data, count) } @@ -65,6 +77,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) return wrappedRead(self.fd, data, count) } @@ -72,6 +85,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) var result = Data(count: count) result.withUnsafeMutableBytes { buffer -> Void in guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { @@ -87,6 +101,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) lseek(self.fd, position, SEEK_SET) } @@ -94,6 +109,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) ftruncate(self.fd, count) } @@ -101,6 +117,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) var value = stat() if fstat(self.fd, &value) == 0 { return value.st_size @@ -113,6 +130,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) return lseek(self.fd, 0, SEEK_CUR); } @@ -121,6 +139,7 @@ public final class ManagedFile { if let queue = self.queue { assert(queue.isCurrent()) } + assert(!self.isClosed) fsync(self.fd) } } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 3206e391f0..0a684dc409 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -1326,7 +1326,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self?.dismissAllTooltips() completion() })]) - controller.dismissed = { [weak self] in + controller.dismissed = { [weak self] _ in self?.isDismissing = false } self.present(controller, in: .window(.root)) @@ -1335,6 +1335,14 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } } + public func shouldDismissImmediately() -> Bool { + if let selectionState = self.interaction?.selectionState, selectionState.count() > 0 { + return false + } else { + return true + } + } + @objc private func cancelPressed() { self.dismissAllTooltips() diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index 5d1de9b2ca..1d76d959b3 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -732,10 +732,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview - let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let previewItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [previewMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, isCentered: true) - let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let dragItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [dragMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, isCentered: true) let headerItems: [ListViewItem] = [previewItem, dragItem] diff --git a/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift b/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift index bc247cb3f5..d79143102f 100644 --- a/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift +++ b/submodules/MediaPlayer/Sources/FFMpegMediaVideoFrameDecoder.swift @@ -125,7 +125,7 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { } } - public func decode(frame: MediaTrackDecodableFrame, ptsOffset: CMTime?, forceARGB: Bool = false) -> MediaTrackFrame? { + public func decode(frame: MediaTrackDecodableFrame, ptsOffset: CMTime?, forceARGB: Bool = false, unpremultiplyAlpha: Bool = true) -> MediaTrackFrame? { if self.isError { return nil } @@ -145,7 +145,7 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { if let ptsOffset = ptsOffset { pts = CMTimeAdd(pts, ptsOffset) } - return convertVideoFrame(self.videoFrame, pts: pts, dts: pts, duration: frame.duration, forceARGB: forceARGB) + return convertVideoFrame(self.videoFrame, pts: pts, dts: pts, duration: frame.duration, forceARGB: forceARGB, unpremultiplyAlpha: unpremultiplyAlpha) } } @@ -268,7 +268,7 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { return UIImage(cgImage: image, scale: 1.0, orientation: .up) } - private func convertVideoFrame(_ frame: FFMpegAVFrame, pts: CMTime, dts: CMTime, duration: CMTime, forceARGB: Bool = false) -> MediaTrackFrame? { + private func convertVideoFrame(_ frame: FFMpegAVFrame, pts: CMTime, dts: CMTime, duration: CMTime, forceARGB: Bool = false, unpremultiplyAlpha: Bool = true) -> MediaTrackFrame? { if frame.data[0] == nil { return nil } @@ -335,7 +335,7 @@ public final class FFMpegMediaVideoFrameDecoder: MediaTrackFrameDecoder { var base: UnsafeMutableRawPointer if pixelFormat == kCVPixelFormatType_32ARGB { let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer) - decodeYUVAPlanesToRGBA(frame.data[0], Int32(frame.lineSize[0]), frame.data[1], Int32(frame.lineSize[1]), frame.data[2], Int32(frame.lineSize[2]), hasAlpha, frame.data[3], CVPixelBufferGetBaseAddress(pixelBuffer)?.assumingMemoryBound(to: UInt8.self), Int32(frame.width), Int32(frame.height), Int32(bytesPerRow)) + decodeYUVAPlanesToRGBA(frame.data[0], Int32(frame.lineSize[0]), frame.data[1], Int32(frame.lineSize[1]), frame.data[2], Int32(frame.lineSize[2]), hasAlpha, frame.data[3], CVPixelBufferGetBaseAddress(pixelBuffer)?.assumingMemoryBound(to: UInt8.self), Int32(frame.width), Int32(frame.height), Int32(bytesPerRow), unpremultiplyAlpha) } else { let srcPlaneSize = Int(frame.lineSize[1]) * Int(frame.height / 2) let uvPlaneSize = srcPlaneSize * 2 diff --git a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift index 3a1233245a..4fc9cead04 100644 --- a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift +++ b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift @@ -59,14 +59,16 @@ public final class SoftwareVideoSource { fileprivate let size: Int32 private let hintVP9: Bool + private let unpremultiplyAlpha: Bool private var enqueuedFrames: [(MediaTrackFrame, CGFloat, CGFloat, Bool)] = [] private var hasReadToEnd: Bool = false - public init(path: String, hintVP9: Bool) { + public init(path: String, hintVP9: Bool, unpremultiplyAlpha: Bool) { let _ = FFMpegMediaFrameSourceContextHelpers.registerFFMpegGlobals self.hintVP9 = hintVP9 + self.unpremultiplyAlpha = unpremultiplyAlpha var s = stat() stat(path, &s) @@ -228,7 +230,7 @@ public final class SoftwareVideoSource { if let maxPts = maxPts, CMTimeCompare(decodableFrame.pts, maxPts) < 0 { ptsOffset = maxPts } - result = (videoStream.decoder.decode(frame: decodableFrame, ptsOffset: ptsOffset, forceARGB: self.hintVP9), CGFloat(videoStream.rotationAngle), CGFloat(videoStream.aspect), loop) + result = (videoStream.decoder.decode(frame: decodableFrame, ptsOffset: ptsOffset, forceARGB: self.hintVP9, unpremultiplyAlpha: self.unpremultiplyAlpha), CGFloat(videoStream.rotationAngle), CGFloat(videoStream.aspect), loop) } else { result = (nil, CGFloat(videoStream.rotationAngle), CGFloat(videoStream.aspect), loop) } diff --git a/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m b/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m index fca53580cf..acf6af66c9 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterAuthAction.m @@ -87,6 +87,8 @@ MTDatacenterAuthMessageService *authService = [[MTDatacenterAuthMessageService alloc] initWithContext:context tempAuth:tempAuth]; authService.delegate = self; [_authMtProto addMessageService:authService]; + + [_authMtProto resume]; } } else diff --git a/submodules/MtProtoKit/Sources/MTDatacenterTransferAuthAction.m b/submodules/MtProtoKit/Sources/MTDatacenterTransferAuthAction.m index cf1740f7af..54e2de78ad 100644 --- a/submodules/MtProtoKit/Sources/MTDatacenterTransferAuthAction.m +++ b/submodules/MtProtoKit/Sources/MTDatacenterTransferAuthAction.m @@ -91,6 +91,8 @@ requestService.forceBackgroundRequests = true; [_sourceDatacenterMtProto addMessageService:requestService]; + [_sourceDatacenterMtProto resume]; + MTRequest *request = [[MTRequest alloc] init]; NSData *exportAuthRequestData = nil; @@ -130,6 +132,8 @@ requestService.forceBackgroundRequests = true; [_destinationDatacenterMtProto addMessageService:requestService]; + [_destinationDatacenterMtProto resume]; + MTRequest *request = [[MTRequest alloc] init]; NSData *importAuthRequestData = [_context.serialization importAuthorization:dataId bytes:authData]; diff --git a/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m b/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m index 45b10c9bed..8cd1ed0a6f 100644 --- a/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m +++ b/submodules/MtProtoKit/Sources/MTDiscoverDatacenterAddressAction.m @@ -96,6 +96,8 @@ _requestService.forceBackgroundRequests = true; [_mtProto addMessageService:_requestService]; + [_mtProto resume]; + MTRequest *request = [[MTRequest alloc] init]; NSData *getConfigData = nil; diff --git a/submodules/MtProtoKit/Sources/MTProto.m b/submodules/MtProtoKit/Sources/MTProto.m index dc89d6b73c..5d892618ae 100644 --- a/submodules/MtProtoKit/Sources/MTProto.m +++ b/submodules/MtProtoKit/Sources/MTProto.m @@ -171,9 +171,11 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64; _sessionInfo = [[MTSessionInfo alloc] initWithRandomSessionIdAndContext:_context]; - - _shouldStayConnected = true; + + _mtState |= MTProtoStatePaused; + + [self setMtState:_mtState | MTProtoStatePaused]; } return self; } diff --git a/submodules/MtProtoKit/Sources/MTRequestMessageService.m b/submodules/MtProtoKit/Sources/MTRequestMessageService.m index 3af49fadbc..e8525fe407 100644 --- a/submodules/MtProtoKit/Sources/MTRequestMessageService.m +++ b/submodules/MtProtoKit/Sources/MTRequestMessageService.m @@ -111,8 +111,8 @@ { if (request.requestContext != nil) { - [_dropReponseContexts addObject:[[MTDropResponseContext alloc] initWithDropMessageId:request.requestContext.messageId]]; - anyNewDropRequests = true; + //[_dropReponseContexts addObject:[[MTDropResponseContext alloc] initWithDropMessageId:request.requestContext.messageId]]; + //anyNewDropRequests = true; } if (request.requestContext.messageId != 0) { diff --git a/submodules/PasscodeUI/Sources/PasscodeLayout.swift b/submodules/PasscodeUI/Sources/PasscodeLayout.swift index 7fb5e8f78b..bd76dad5b8 100644 --- a/submodules/PasscodeUI/Sources/PasscodeLayout.swift +++ b/submodules/PasscodeUI/Sources/PasscodeLayout.swift @@ -67,7 +67,7 @@ struct PasscodeKeyboardLayout { self.topOffset = 226.0 self.biometricsOffset = 30.0 self.deleteOffset = 20.0 - case .iPhoneX, .iPhone12Mini, .iPhone12: + case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro: self.buttonSize = 75.0 self.horizontalSecond = 103.0 self.horizontalThird = 206.0 @@ -78,7 +78,7 @@ struct PasscodeKeyboardLayout { self.topOffset = 294.0 self.biometricsOffset = 30.0 self.deleteOffset = 20.0 - case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax: + case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax: self.buttonSize = 85.0 self.horizontalSecond = 115.0 self.horizontalThird = 230.0 @@ -151,11 +151,11 @@ public struct PasscodeLayout { self.titleOffset = 112.0 self.subtitleOffset = -6.0 self.inputFieldOffset = 156.0 - case .iPhoneX, .iPhone12Mini, .iPhone12: + case .iPhoneX, .iPhone12Mini, .iPhone12, .iPhone13Mini, .iPhone13, .iPhone13Pro: self.titleOffset = 162.0 self.subtitleOffset = 0.0 self.inputFieldOffset = 206.0 - case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax: + case .iPhoneXSMax, .iPhoneXr, .iPhone12ProMax, .iPhone13ProMax: self.titleOffset = 180.0 self.subtitleOffset = 0.0 self.inputFieldOffset = 226.0 diff --git a/submodules/Pasteboard/Sources/Pasteboard.swift b/submodules/Pasteboard/Sources/Pasteboard.swift index 203d275a49..b25ab49f55 100644 --- a/submodules/Pasteboard/Sources/Pasteboard.swift +++ b/submodules/Pasteboard/Sources/Pasteboard.swift @@ -6,7 +6,17 @@ import MobileCoreServices import TextFormat private func rtfStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> String { - let test = stringWithAppliedEntities(text, entities: entities, baseColor: .black, linkColor: .black, baseFont: Font.regular(14.0), linkFont: Font.regular(14.0), boldFont: Font.semibold(14.0), italicFont: Font.italic(14.0), boldItalicFont: Font.semiboldItalic(14.0), fixedFont: Font.monospace(14.0), blockQuoteFont: Font.regular(14.0), underlineLinks: false, external: true) + let sourceString = stringWithAppliedEntities(text, entities: entities, baseColor: .black, linkColor: .black, baseFont: Font.regular(14.0), linkFont: Font.regular(14.0), boldFont: Font.semibold(14.0), italicFont: Font.italic(14.0), boldItalicFont: Font.semiboldItalic(14.0), fixedFont: Font.monospace(14.0), blockQuoteFont: Font.regular(14.0), underlineLinks: false, external: true, message: nil) + let test = NSMutableAttributedString(attributedString: sourceString) + + var index = 0 + test.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: sourceString.length), using: { value, range, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + test.addAttribute(NSAttributedString.Key.link, value: URL(string: "tg://emoji?id=\(value.fileId)&t=\(index)")!, range: range) + index += 1 + } + }) + test.removeAttribute(ChatTextInputAttributes.customEmoji, range: NSRange(location: 0, length: test.length)) if let data = try? test.data(from: NSRange(location: 0, length: test.length), documentAttributes: [NSAttributedString.DocumentAttributeKey.documentType: NSAttributedString.DocumentType.rtf]) { if var rtf = String(data: data, encoding: .windowsCP1252) { @@ -51,13 +61,33 @@ private func chatInputStateString(attributedString: NSAttributedString) -> NSAtt if let _ = attributes[.underlineStyle] { string.addAttribute(ChatTextInputAttributes.underline, value: true as NSNumber, range: range) } + if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + string.addAttribute(ChatTextInputAttributes.customEmoji, value: value, range: range) + } }) return string } public func chatInputStateStringFromRTF(_ data: Data, type: NSAttributedString.DocumentType) -> NSAttributedString? { if let attributedString = try? NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: type], documentAttributes: nil) { - return chatInputStateString(attributedString: attributedString) + let updatedString = NSMutableAttributedString(attributedString: attributedString) + updatedString.enumerateAttribute(NSAttributedString.Key.link, in: NSRange(location: 0, length: attributedString.length), using: { value, range, _ in + if let url = value as? URL, url.scheme == "tg", url.host == "emoji" { + var emojiId: Int64? + if let queryItems = URLComponents(string: url.absoluteString)?.queryItems { + for item in queryItems { + if item.name == "id" { + emojiId = item.value.flatMap(Int64.init) + } + } + } + if let emojiId = emojiId { + updatedString.removeAttribute(NSAttributedString.Key.link, range: range) + updatedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: emojiId, file: nil), range: range) + } + } + }) + return chatInputStateString(attributedString: updatedString) } return nil } diff --git a/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift b/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift index 9c6b04205a..0b898dd5a9 100644 --- a/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelOwnershipTransferController.swift @@ -438,7 +438,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, u controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.inputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() disposable.dispose() } diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index 7294747475..a9c5c4595f 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -375,7 +375,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index 9335c9ee04..78ea869c99 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -532,12 +532,25 @@ private func chatMessageVideoDatas(postbox: Postbox, fileReference: FileMediaRef return thumbnail |> mapToSignal { thumbnailData in - return combineLatest(fullSizeDataAndPath, reducedSizeDataAndPath) - |> map { fullSize, reducedSize in - if !fullSize._1 && reducedSize._1 { - return Tuple(thumbnailData, reducedSize._0, false) + if synchronousLoad, let thumbnailData = thumbnailData { + return .single(Tuple(thumbnailData, nil, false)) + |> then( + combineLatest(fullSizeDataAndPath, reducedSizeDataAndPath) + |> map { fullSize, reducedSize in + if !fullSize._1 && reducedSize._1 { + return Tuple(thumbnailData, reducedSize._0, false) + } + return Tuple(thumbnailData, fullSize._0, fullSize._1) + } + ) + } else { + return combineLatest(fullSizeDataAndPath, reducedSizeDataAndPath) + |> map { fullSize, reducedSize in + if !fullSize._1 && reducedSize._1 { + return Tuple(thumbnailData, reducedSize._0, false) + } + return Tuple(thumbnailData, fullSize._0, fullSize._1) } - return Tuple(thumbnailData, fullSize._0, fullSize._1) } } } diff --git a/submodules/Postbox/Sources/ChatListViewState.swift b/submodules/Postbox/Sources/ChatListViewState.swift index 100ea0fb22..baf350c840 100644 --- a/submodules/Postbox/Sources/ChatListViewState.swift +++ b/submodules/Postbox/Sources/ChatListViewState.swift @@ -96,7 +96,7 @@ private func updateMessagePeers(_ message: Message, updatedPeers: [PeerId: Peer] peers[peerId] = currentPeer } } - return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds) + return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia) } return nil } diff --git a/submodules/Postbox/Sources/GlobalMessageTagsView.swift b/submodules/Postbox/Sources/GlobalMessageTagsView.swift index c67851ba44..0466e20cbb 100644 --- a/submodules/Postbox/Sources/GlobalMessageTagsView.swift +++ b/submodules/Postbox/Sources/GlobalMessageTagsView.swift @@ -167,7 +167,7 @@ final class MutableGlobalMessageTagsView: MutablePostboxView { hasChanges = true } case let .message(message): - if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds))) { + if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia))) { hasChanges = true } } diff --git a/submodules/Postbox/Sources/Media.swift b/submodules/Postbox/Sources/Media.swift index 0673d04a03..68e7a23038 100644 --- a/submodules/Postbox/Sources/Media.swift +++ b/submodules/Postbox/Sources/Media.swift @@ -68,10 +68,6 @@ public struct MediaId: Hashable, PostboxCoding, CustomStringConvertible, Codable } } -public protocol AssociatedMediaData: AnyObject, PostboxCoding { - func isEqual(to: AssociatedMediaData) -> Bool -} - public protocol Media: AnyObject, PostboxCoding { var id: MediaId? { get } var peerIds: [PeerId] { get } diff --git a/submodules/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index 341b196a8b..f1cbdb1419 100644 --- a/submodules/Postbox/Sources/MediaBox.swift +++ b/submodules/Postbox/Sources/MediaBox.swift @@ -188,7 +188,8 @@ public final class MediaBox { self.timeBasedCleanup = TimeBasedCleanup(generalPaths: [ self.basePath, - self.basePath + "/cache" + self.basePath + "/cache", + self.basePath + "/animation-cache" ], shortLivedPaths: [ self.basePath + "/short-cache" ]) @@ -1238,6 +1239,27 @@ public final class MediaBox { } } + func processRecursive(directoryPath: String, subdirectoryPath: String) { + if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: directoryPath), includingPropertiesForKeys: [.fileSizeKey, .isDirectoryKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) { + loop: for url in enumerator { + if let url = url as? URL { + if let prefix = url.lastPathComponent.components(separatedBy: ":").first, excludePrefixes.contains(prefix) { + continue loop + } + + if let isDirectory = (try? url.resourceValues(forKeys: Set([.isDirectoryKey])))?.isDirectory, isDirectory { + processRecursive(directoryPath: url.path, subdirectoryPath: subdirectoryPath + "/\(url.lastPathComponent)") + } else if let value = (try? url.resourceValues(forKeys: Set([.fileSizeKey])))?.fileSize, value != 0 { + paths.append("\(subdirectoryPath)/" + url.lastPathComponent) + cacheResult += Int64(value) + } + } + } + } + } + + processRecursive(directoryPath: self.basePath + "/animation-cache", subdirectoryPath: "animation-cache") + if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: self.basePath + "/short-cache"), includingPropertiesForKeys: [.fileSizeKey], options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants], errorHandler: nil) { loop: for url in enumerator { if let url = url as? URL { diff --git a/submodules/Postbox/Sources/MediaBoxFile.swift b/submodules/Postbox/Sources/MediaBoxFile.swift index 578f1a82b2..aeb69d5829 100644 --- a/submodules/Postbox/Sources/MediaBoxFile.swift +++ b/submodules/Postbox/Sources/MediaBoxFile.swift @@ -108,7 +108,7 @@ private final class MediaBoxFileMap { return nil } - if count < 0 || length < 4 + 4 + count * 2 * 4 { + if count < 0 || UInt64(length) < 4 + 4 + UInt64(count) * 2 * 4 { return nil } diff --git a/submodules/Postbox/Sources/Message.swift b/submodules/Postbox/Sources/Message.swift index 8bf7ad9ed6..5a152b6a1c 100644 --- a/submodules/Postbox/Sources/Message.swift +++ b/submodules/Postbox/Sources/Message.swift @@ -576,6 +576,7 @@ public struct MessageForwardInfo: Equatable { public protocol MessageAttribute: AnyObject, PostboxCoding { var associatedPeerIds: [PeerId] { get } var associatedMessageIds: [MessageId] { get } + var associatedMediaIds: [MediaId] { get } var automaticTimestampBasedAttribute: (UInt16, Int32)? { get } } @@ -588,6 +589,10 @@ public extension MessageAttribute { return [] } + var associatedMediaIds: [MediaId] { + return [] + } + var automaticTimestampBasedAttribute: (UInt16, Int32)? { return nil } @@ -619,12 +624,13 @@ public final class Message { public let peers: SimpleDictionary public let associatedMessages: SimpleDictionary public let associatedMessageIds: [MessageId] + public let associatedMedia: [MediaId: Media] public var index: MessageIndex { return MessageIndex(id: self.id, timestamp: self.timestamp) } - public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary, associatedMessages: SimpleDictionary, associatedMessageIds: [MessageId]) { + public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary, associatedMessages: SimpleDictionary, associatedMessageIds: [MessageId], associatedMedia: [MediaId: Media]) { self.stableId = stableId self.stableVersion = stableVersion self.id = id @@ -645,46 +651,47 @@ public final class Message { self.peers = peers self.associatedMessages = associatedMessages self.associatedMessageIds = associatedMessageIds + self.associatedMedia = associatedMedia } public func withUpdatedText(_ text: String) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedTimestamp(_ timestamp: Int32) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedMedia(_ media: [Media]) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedPeers(_ peers: SimpleDictionary) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedFlags(_ flags: MessageFlags) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } func withUpdatedGroupInfo(_ groupInfo: MessageGroupInfo?) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedAttributes(_ attributes: [MessageAttribute]) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } func withUpdatedAssociatedMessages(_ associatedMessages: SimpleDictionary) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedForwardInfo(_ forwardInfo: MessageForwardInfo?) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } public func withUpdatedAuthor(_ author: Peer?) -> Message { - return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds) + return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia) } } diff --git a/submodules/Postbox/Sources/MessageHistoryTable.swift b/submodules/Postbox/Sources/MessageHistoryTable.swift index b61d5c8e3f..57689a4d46 100644 --- a/submodules/Postbox/Sources/MessageHistoryTable.swift +++ b/submodules/Postbox/Sources/MessageHistoryTable.swift @@ -548,6 +548,18 @@ final class MessageHistoryTable: Table { } } + func storeMediaIfNotPresent(media: Media) { + guard let id = media.id else { + return + } + if let _ = self.messageMediaTable.get(id, embedded: { index, id in + return self.embeddedMediaForIndex(index, id: id) + }) { + } else { + let _ = self.messageMediaTable.set(media, index: nil, messageHistoryTable: self) + } + } + func getMedia(_ id: MediaId) -> Media? { return self.messageMediaTable.get(id, embedded: { index, id in return self.embeddedMediaForIndex(index, id: id) @@ -2516,12 +2528,23 @@ final class MessageHistoryTable: Table { var associatedMessageIds: [MessageId] = [] var associatedMessages = SimpleDictionary() + var associatedMedia: [MediaId: Media] = [:] for attribute in parsedAttributes { for peerId in attribute.associatedPeerIds { if let peer = peerTable.get(peerId) { peers[peer.id] = peer } } + for mediaId in attribute.associatedMediaIds { + if associatedMedia[mediaId] == nil { + if mediaId.id == 5364107552168613887 { + assert(true) + } + if let media = self.getMedia(mediaId) { + associatedMedia[mediaId] = media + } + } + } associatedMessageIds.append(contentsOf: attribute.associatedMessageIds) if addAssociatedMessages { for messageId in attribute.associatedMessageIds { @@ -2534,7 +2557,7 @@ final class MessageHistoryTable: Table { } } - return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds) + return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds, associatedMedia: associatedMedia) } func renderMessagePeers(_ message: Message, peerTable: PeerTable) -> Message { diff --git a/submodules/Postbox/Sources/MessageHistoryView.swift b/submodules/Postbox/Sources/MessageHistoryView.swift index 04a3cf9518..8e1c377176 100644 --- a/submodules/Postbox/Sources/MessageHistoryView.swift +++ b/submodules/Postbox/Sources/MessageHistoryView.swift @@ -137,7 +137,7 @@ enum MutableMessageHistoryEntry { return .IntermediateMessageEntry(updatedMessage, location, monthLocation) case let .MessageEntry(value, reloadAssociatedMessages, reloadPeers): let message = value.message - let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds) + let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia) return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers) } } diff --git a/submodules/Postbox/Sources/MessageHistoryViewState.swift b/submodules/Postbox/Sources/MessageHistoryViewState.swift index c5cde494f1..5457bc92d5 100644 --- a/submodules/Postbox/Sources/MessageHistoryViewState.swift +++ b/submodules/Postbox/Sources/MessageHistoryViewState.swift @@ -1239,7 +1239,7 @@ final class HistoryViewLoadedState { messageMedia.append(media) } } - let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds) + let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia) return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers) } case .IntermediateMessageEntry: diff --git a/submodules/Postbox/Sources/MessageMediaTable.swift b/submodules/Postbox/Sources/MessageMediaTable.swift index f283334706..40dd4be676 100644 --- a/submodules/Postbox/Sources/MessageMediaTable.swift +++ b/submodules/Postbox/Sources/MessageMediaTable.swift @@ -31,6 +31,10 @@ final class MessageMediaTable: Table { return key } + func exists(id: MediaId) -> Bool { + return self.valueBox.exists(self.table, key: self.key(id)) + } + func get(_ id: MediaId, embedded: (MessageIndex, MediaId) -> Media?) -> (MessageIndex?, Media)? { if let value = self.valueBox.get(self.table, key: self.key(id)) { var type: Int8 = 0 @@ -63,7 +67,7 @@ final class MessageMediaTable: Table { return nil } - func set(_ media: Media, index: MessageIndex, messageHistoryTable: MessageHistoryTable, sharedWriteBuffer: WriteBuffer = WriteBuffer(), sharedEncoder: PostboxEncoder = PostboxEncoder()) -> InsertMediaResult { + func set(_ media: Media, index: MessageIndex?, messageHistoryTable: MessageHistoryTable, sharedWriteBuffer: WriteBuffer = WriteBuffer(), sharedEncoder: PostboxEncoder = PostboxEncoder()) -> InsertMediaResult { if let id = media.id { if let value = self.valueBox.get(self.table, key: self.key(id)) { var type: Int8 = 0 @@ -126,23 +130,45 @@ final class MessageMediaTable: Table { return .Embed(media) } } else { - sharedWriteBuffer.reset() - var type: Int8 = MediaEntryType.MessageReference.rawValue - sharedWriteBuffer.write(&type, offset: 0, length: 1) - var idPeerId: Int64 = index.id.peerId.toInt64() - var idNamespace: Int32 = index.id.namespace - var idId: Int32 = index.id.id - var idTimestamp: Int32 = index.timestamp - sharedWriteBuffer.write(&idPeerId, offset: 0, length: 8) - sharedWriteBuffer.write(&idNamespace, offset: 0, length: 4) - sharedWriteBuffer.write(&idId, offset: 0, length: 4) - sharedWriteBuffer.write(&idTimestamp, offset: 0, length: 4) - - withExtendedLifetime(sharedWriteBuffer, { - self.valueBox.set(self.table, key: self.key(id), value: sharedWriteBuffer.readBufferNoCopy()) - }) - - return .Embed(media) + if let index = index { + sharedWriteBuffer.reset() + var type: Int8 = MediaEntryType.MessageReference.rawValue + sharedWriteBuffer.write(&type, offset: 0, length: 1) + var idPeerId: Int64 = index.id.peerId.toInt64() + var idNamespace: Int32 = index.id.namespace + var idId: Int32 = index.id.id + var idTimestamp: Int32 = index.timestamp + sharedWriteBuffer.write(&idPeerId, offset: 0, length: 8) + sharedWriteBuffer.write(&idNamespace, offset: 0, length: 4) + sharedWriteBuffer.write(&idId, offset: 0, length: 4) + sharedWriteBuffer.write(&idTimestamp, offset: 0, length: 4) + + withExtendedLifetime(sharedWriteBuffer, { + self.valueBox.set(self.table, key: self.key(id), value: sharedWriteBuffer.readBufferNoCopy()) + }) + + return .Embed(media) + } else { + sharedWriteBuffer.reset() + var directType: Int8 = MediaEntryType.Direct.rawValue + sharedWriteBuffer.write(&directType, offset: 0, length: 1) + + sharedEncoder.reset() + sharedEncoder.encodeRootObject(media) + let mediaBuffer = sharedEncoder.memoryBuffer() + var mediaBufferLength = Int32(mediaBuffer.length) + sharedWriteBuffer.write(&mediaBufferLength, offset: 0, length: 4) + sharedWriteBuffer.write(mediaBuffer.memory, offset: 0, length: mediaBuffer.length) + + var messageReferenceCount: Int32 = 2 + sharedWriteBuffer.write(&messageReferenceCount, offset: 0, length: 4) + + withExtendedLifetime(sharedWriteBuffer, { + self.valueBox.set(self.table, key: self.key(id), value: sharedWriteBuffer.readBufferNoCopy()) + }) + + return .Reference + } } } else { return .Embed(media) diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index dded53e249..1af2ada131 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -529,6 +529,11 @@ public final class Transaction { return self.postbox?.updateMedia(id, update: update) ?? Set() } + public func storeMediaIfNotPresent(media: Media) { + assert(!self.disposed) + self.postbox?.storeMediaIfNotPresent(media: media) + } + public func replaceItemCollections(namespace: ItemCollectionId.Namespace, itemCollections: [(ItemCollectionId, ItemCollectionInfo, [ItemCollectionItem])]) { assert(!self.disposed) self.postbox?.replaceItemCollections(namespace: namespace, itemCollections: itemCollections) @@ -735,6 +740,14 @@ public final class Transaction { return Set() } + public func filterStoredMediaIds(namespace: MediaId.Namespace, ids: Set) -> Set { + assert(!self.disposed) + if let postbox = self.postbox { + return postbox.filterStoredMediaIds(namespace: namespace, ids: ids) + } + return Set() + } + public func storedMessageId(peerId: PeerId, namespace: MessageId.Namespace, timestamp: Int32) -> MessageId? { assert(!self.disposed) return self.postbox?.storedMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp) @@ -2295,6 +2308,10 @@ final class PostboxImpl { return updatedMessageIndices } + fileprivate func storeMediaIfNotPresent(media: Media) { + self.messageHistoryTable.storeMediaIfNotPresent(media: media) + } + fileprivate func replaceItemCollections(namespace: ItemCollectionId.Namespace, itemCollections: [(ItemCollectionId, ItemCollectionInfo, [ItemCollectionItem])]) { var infos: [(ItemCollectionId, ItemCollectionInfo)] = [] for (id, info, items) in itemCollections { @@ -2343,6 +2360,18 @@ final class PostboxImpl { return filteredIds } + fileprivate func filterStoredMediaIds(namespace: MediaId.Namespace, ids: Set) -> Set { + var filteredIds = Set() + + for id in ids { + if !self.mediaTable.exists(id: MediaId(namespace: namespace, id: id)) { + filteredIds.insert(id) + } + } + + return filteredIds + } + fileprivate func storedMessageId(peerId: PeerId, namespace: MessageId.Namespace, timestamp: Int32) -> MessageId? { if let id = self.messageHistoryTable.findMessageId(peerId: peerId, namespace: namespace, timestamp: timestamp), id.namespace == namespace { return id diff --git a/submodules/Postbox/Sources/TimeBasedCleanup.swift b/submodules/Postbox/Sources/TimeBasedCleanup.swift index 2510fad261..685dbb6e09 100644 --- a/submodules/Postbox/Sources/TimeBasedCleanup.swift +++ b/submodules/Postbox/Sources/TimeBasedCleanup.swift @@ -13,7 +13,7 @@ private struct ScanFilesResult { var totalSize: UInt64 = 0 } -private func printOpenFiles() { +public func printOpenFiles() { var flags: Int32 = 0 var fd: Int32 = 0 var buf = Data(count: Int(MAXPATHLEN) + 1) diff --git a/submodules/PremiumUI/BUILD b/submodules/PremiumUI/BUILD index 4728a45871..cbb0e38f16 100644 --- a/submodules/PremiumUI/BUILD +++ b/submodules/PremiumUI/BUILD @@ -82,7 +82,6 @@ swift_library( "//submodules/Components/SheetComponent:SheetComponent", "//submodules/Components/BundleIconComponent:BundleIconComponent", "//submodules/Components/SolidRoundedButtonComponent:SolidRoundedButtonComponent", - "//submodules/Components/Forms/PrefixSectionGroupComponent:PrefixSectionGroupComponent", "//submodules/InAppPurchaseManager:InAppPurchaseManager", "//submodules/ConfettiEffect:ConfettiEffect", "//submodules/TextFormat:TextFormat", @@ -93,6 +92,7 @@ swift_library( "//submodules/RadialStatusNode:RadialStatusNode", "//submodules/ShimmerEffect:ShimmerEffect", "//submodules/LegacyComponents:LegacyComponents", + "//submodules/CheckNode:CheckNode", ], visibility = [ "//visibility:public", diff --git a/submodules/PremiumUI/Resources/emoji.scn b/submodules/PremiumUI/Resources/emoji.scn new file mode 100644 index 0000000000..adca0e2664 Binary files /dev/null and b/submodules/PremiumUI/Resources/emoji.scn differ diff --git a/submodules/PremiumUI/Resources/gift.scn b/submodules/PremiumUI/Resources/gift.scn new file mode 100644 index 0000000000..14f72e0681 Binary files /dev/null and b/submodules/PremiumUI/Resources/gift.scn differ diff --git a/submodules/PremiumUI/Resources/smilie.png b/submodules/PremiumUI/Resources/smilie.png new file mode 100644 index 0000000000..e88beb0022 Binary files /dev/null and b/submodules/PremiumUI/Resources/smilie.png differ diff --git a/submodules/PremiumUI/Resources/sunglasses.png b/submodules/PremiumUI/Resources/sunglasses.png new file mode 100644 index 0000000000..87f51368ba Binary files /dev/null and b/submodules/PremiumUI/Resources/sunglasses.png differ diff --git a/submodules/PremiumUI/Resources/thumbsup.png b/submodules/PremiumUI/Resources/thumbsup.png new file mode 100644 index 0000000000..3b13d58b2f Binary files /dev/null and b/submodules/PremiumUI/Resources/thumbsup.png differ diff --git a/submodules/PremiumUI/Sources/BadgeStarsView.swift b/submodules/PremiumUI/Sources/BadgeStarsView.swift index 78c59637bd..6ca220ce3a 100644 --- a/submodules/PremiumUI/Sources/BadgeStarsView.swift +++ b/submodules/PremiumUI/Sources/BadgeStarsView.swift @@ -57,3 +57,57 @@ final class BadgeStarsView: UIView, PhoneDemoDecorationView { self.sceneView.frame = CGRect(origin: .zero, size: frame.size) } } + +final class EmojiStarsView: UIView, PhoneDemoDecorationView { + private let sceneView: SCNView + + private var leftParticles: SCNNode? + private var rightParticles: SCNNode? + + override init(frame: CGRect) { + self.sceneView = SCNView(frame: CGRect(origin: .zero, size: frame.size)) + self.sceneView.backgroundColor = .clear + if let url = getAppBundle().url(forResource: "emoji", withExtension: "scn") { + self.sceneView.scene = try? SCNScene(url: url, options: nil) + } + self.sceneView.isUserInteractionEnabled = false + self.sceneView.preferredFramesPerSecond = 60 + + super.init(frame: frame) + + self.alpha = 0.0 + + self.addSubview(self.sceneView) + + self.leftParticles = self.sceneView.scene?.rootNode.childNode(withName: "leftParticles", recursively: false) + self.rightParticles = self.sceneView.scene?.rootNode.childNode(withName: "rightParticles", recursively: false) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func setVisible(_ visible: Bool) { + if visible, let leftParticles = self.leftParticles, let rightParticles = self.rightParticles, leftParticles.parent == nil { + self.sceneView.scene?.rootNode.addChildNode(leftParticles) + self.sceneView.scene?.rootNode.addChildNode(rightParticles) + } + + let transition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear) + transition.updateAlpha(layer: self.layer, alpha: visible ? 0.5 : 0.0, completion: { [weak self] finished in + if let strongSelf = self, finished && !visible && strongSelf.leftParticles?.parent != nil { + strongSelf.leftParticles?.removeFromParentNode() + strongSelf.rightParticles?.removeFromParentNode() + } + }) + } + + func resetAnimation() { + } + + override func layoutSubviews() { + super.layoutSubviews() + + self.sceneView.frame = CGRect(origin: .zero, size: frame.size) + } +} diff --git a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift new file mode 100644 index 0000000000..668a2e6a1f --- /dev/null +++ b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift @@ -0,0 +1,295 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import SwiftSignalKit +import SceneKit +import GZip +import AppBundle +import LegacyComponents +import AvatarNode +import AccountContext +import TelegramCore + +private let sceneVersion: Int = 3 + +private func deg2rad(_ number: Float) -> Float { + return number * .pi / 180 +} + +private func rad2deg(_ number: Float) -> Float { + return number * 180.0 / .pi +} + +private func generateParticlesTexture() -> UIImage { + return UIImage() +} + +private func generateFlecksTexture() -> UIImage { + return UIImage() +} + +private func generateShineTexture() -> UIImage { + return UIImage() +} + +private func generateDiffuseTexture() -> UIImage { + return generateImage(CGSize(width: 256, height: 256), rotatedContext: { size, context in + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x0079ff).cgColor, + UIColor(rgb: 0x6a93ff).cgColor, + UIColor(rgb: 0x9172fe).cgColor, + UIColor(rgb: 0xe46acd).cgColor, + ] + var locations: [CGFloat] = [0.0, 0.25, 0.5, 0.75, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + })! +} + +class GiftAvatarComponent: Component { + let context: AccountContext + let peer: EnginePeer? + let isVisible: Bool + let hasIdleAnimations: Bool + + init(context: AccountContext, peer: EnginePeer?, isVisible: Bool, hasIdleAnimations: Bool) { + self.context = context + self.peer = peer + self.isVisible = isVisible + self.hasIdleAnimations = hasIdleAnimations + } + + static func ==(lhs: GiftAvatarComponent, rhs: GiftAvatarComponent) -> Bool { + return lhs.peer == rhs.peer && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations + } + + final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView { + final class Tag { + } + + func matches(tag: Any) -> Bool { + if let _ = tag as? Tag { + return true + } + return false + } + + private var _ready = Promise() + var ready: Signal { + return self._ready.get() + } + + weak var animateFrom: UIView? + weak var containerView: UIView? + var animationColor: UIColor? + + private let sceneView: SCNView + private let avatarNode: ImageNode + + private var previousInteractionTimestamp: Double = 0.0 + private var timer: SwiftSignalKit.Timer? + private var hasIdleAnimations = false + + override init(frame: CGRect) { + self.sceneView = SCNView(frame: CGRect(origin: .zero, size: CGSize(width: 64.0, height: 64.0))) + self.sceneView.backgroundColor = .clear + self.sceneView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) + self.sceneView.isUserInteractionEnabled = false + self.sceneView.preferredFramesPerSecond = 60 + + self.avatarNode = ImageNode() + self.avatarNode.displaysAsynchronously = false + + super.init(frame: frame) + + self.addSubview(self.sceneView) + self.addSubview(self.avatarNode.view) + + self.setup() + + let panGestureRecoginzer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:))) + self.addGestureRecognizer(panGestureRecoginzer) + + let tapGestureRecoginzer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) + self.addGestureRecognizer(tapGestureRecoginzer) + + self.disablesInteractiveModalDismiss = true + self.disablesInteractiveTransitionGestureRecognizer = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.timer?.invalidate() + } + + private let hapticFeedback = HapticFeedback() + + private var delayTapsTill: Double? + @objc private func handleTap(_ gesture: UITapGestureRecognizer) { + self.playAppearanceAnimation(velocity: nil, mirror: false, explode: true) + } + + private var previousYaw: Float = 0.0 + @objc private func handlePan(_ gesture: UIPanGestureRecognizer) { + guard let scene = self.sceneView.scene, let node = scene.rootNode.childNode(withName: "star", recursively: false) else { + return + } + + self.previousInteractionTimestamp = CACurrentMediaTime() + + if #available(iOS 11.0, *) { + node.removeAnimation(forKey: "rotate", blendOutDuration: 0.1) + node.removeAnimation(forKey: "tapRotate", blendOutDuration: 0.1) + } else { + node.removeAllAnimations() + } + + switch gesture.state { + case .began: + self.previousYaw = 0.0 + case .changed: + let translation = gesture.translation(in: gesture.view) + let yawPan = deg2rad(Float(translation.x)) + + func rubberBandingOffset(offset: CGFloat, bandingStart: CGFloat) -> CGFloat { + let bandedOffset = offset - bandingStart + let range: CGFloat = 60.0 + let coefficient: CGFloat = 0.4 + return bandingStart + (1.0 - (1.0 / ((bandedOffset * coefficient / range) + 1.0))) * range + } + + var pitchTranslation = rubberBandingOffset(offset: abs(translation.y), bandingStart: 0.0) + if translation.y < 0.0 { + pitchTranslation *= -1.0 + } + let pitchPan = deg2rad(Float(pitchTranslation)) + + self.previousYaw = yawPan + node.eulerAngles = SCNVector3(pitchPan, yawPan, 0.0) + case .ended: + let velocity = gesture.velocity(in: gesture.view) + + var smallAngle = false + if (self.previousYaw < .pi / 2 && self.previousYaw > -.pi / 2) && abs(velocity.x) < 200 { + smallAngle = true + } + + self.playAppearanceAnimation(velocity: velocity.x, smallAngle: smallAngle, explode: !smallAngle && abs(velocity.x) > 600) + node.eulerAngles = SCNVector3(0.0, 0.0, 0.0) + default: + break + } + } + + private func setup() { + guard let url = getAppBundle().url(forResource: "gift", withExtension: "scn"), let scene = try? SCNScene(url: url, options: nil) else { + return + } + + self.sceneView.scene = scene + self.sceneView.delegate = self + + let _ = self.sceneView.snapshot() + } + + private var didSetReady = false + func renderer(_ renderer: SCNSceneRenderer, didRenderScene scene: SCNScene, atTime time: TimeInterval) { + if !self.didSetReady { + self.didSetReady = true + + Queue.mainQueue().justDispatch { + self._ready.set(.single(true)) + self.onReady() + } + } + } + + private func onReady() { + self.playAppearanceAnimation(explode: true) + + self.previousInteractionTimestamp = CACurrentMediaTime() + self.timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: true, completion: { [weak self] in + if let strongSelf = self, strongSelf.hasIdleAnimations { + let currentTimestamp = CACurrentMediaTime() + if currentTimestamp > strongSelf.previousInteractionTimestamp + 5.0 { + strongSelf.playAppearanceAnimation() + } + } + }, queue: Queue.mainQueue()) + self.timer?.start() + } + + private func playAppearanceAnimation(velocity: CGFloat? = nil, smallAngle: Bool = false, mirror: Bool = false, explode: Bool = false) { + guard let scene = self.sceneView.scene else { + return + } + + let currentTime = CACurrentMediaTime() + self.previousInteractionTimestamp = currentTime + self.delayTapsTill = currentTime + 0.85 + + if explode, let node = scene.rootNode.childNode(withName: "swirl", recursively: false), let particles = scene.rootNode.childNode(withName: "particles", recursively: false) { + if let particleSystem = particles.particleSystems?.first { + particleSystem.particleColorVariation = SCNVector4(0.15, 0.2, 0.15, 0.3) + particleSystem.speedFactor = 2.0 + particleSystem.particleVelocity = 2.2 + particleSystem.birthRate = 4.0 + particleSystem.particleLifeSpan = 2.0 + + node.physicsField?.isActive = true + Queue.mainQueue().after(1.0) { + node.physicsField?.isActive = false + particles.particleSystems?.first?.birthRate = 1.2 + particleSystem.particleVelocity = 1.0 + particleSystem.particleLifeSpan = 4.0 + + let animation = POPBasicAnimation() + animation.property = (POPAnimatableProperty.property(withName: "speedFactor", initializer: { property in + property?.readBlock = { particleSystem, values in + values?.pointee = (particleSystem as! SCNParticleSystem).speedFactor + } + property?.writeBlock = { particleSystem, values in + (particleSystem as! SCNParticleSystem).speedFactor = values!.pointee + } + property?.threshold = 0.01 + }) as! POPAnimatableProperty) + animation.fromValue = 2.0 as NSNumber + animation.toValue = 1.0 as NSNumber + animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) + animation.duration = 0.5 + particleSystem.pop_add(animation, forKey: "speedFactor") + } + } + } + } + + func update(component: GiftAvatarComponent, availableSize: CGSize, transition: Transition) -> CGSize { + self.sceneView.bounds = CGRect(origin: .zero, size: CGSize(width: availableSize.width * 2.0, height: availableSize.height * 2.0)) + if self.sceneView.superview == self { + self.sceneView.center = CGPoint(x: availableSize.width / 2.0, y: availableSize.height / 2.0) + } + + self.hasIdleAnimations = component.hasIdleAnimations + let avatarSize = CGSize(width: 100.0, height: 100.0) + if let peer = component.peer { + self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: peer, size: avatarSize, font: avatarPlaceholderFont(size: 43.0), fullSize: true)) + } + self.avatarNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - avatarSize.width) / 2.0), y: 63.0), size: avatarSize) + + return availableSize + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} diff --git a/submodules/PremiumUI/Sources/PhoneDemoComponent.swift b/submodules/PremiumUI/Sources/PhoneDemoComponent.swift index 6005dbd665..a55181c69a 100644 --- a/submodules/PremiumUI/Sources/PhoneDemoComponent.swift +++ b/submodules/PremiumUI/Sources/PhoneDemoComponent.swift @@ -310,6 +310,7 @@ final class PhoneDemoComponent: Component { case swirlStars case fasterStars case badgeStars + case emoji } let context: AccountContext @@ -452,6 +453,13 @@ final class PhoneDemoComponent: Component { self.decorationView = starsView self.decorationContainerView.addSubview(starsView) } + case .emoji: + if let _ = self.decorationView as? EmojiStarsView { + } else { + let starsView = EmojiStarsView(frame: self.decorationContainerView.bounds) + self.decorationView = starsView + self.decorationContainerView.addSubview(starsView) + } } self.phoneView.setup(context: component.context, videoFile: component.videoFile, position: component.position) diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index f510ecf189..0095bff066 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -485,7 +485,7 @@ private final class DemoSheetContent: CombinedComponent { self.context = context self.subject = subject self.source = source - self.order = order ?? [.moreUpload, .fasterDownload, .voiceToText, .noAds, .uniqueReactions, .premiumStickers, .advancedChatManagement, .profileBadge, .animatedUserpics, .appIcons] + self.order = order ?? [.moreUpload, .fasterDownload, .voiceToText, .noAds, .uniqueReactions, .premiumStickers, .animatedEmoji, .advancedChatManagement, .profileBadge, .animatedUserpics, .appIcons] self.action = action self.dismiss = dismiss } @@ -551,7 +551,7 @@ private final class DemoSheetContent: CombinedComponent { self.context.engine.stickers.availableReactions(), self.context.account.postbox.combinedView(keys: [stickersKey]) |> map { views -> [OrderedItemListEntry]? in - if let view = views.views[stickersKey] as? OrderedItemListView, !view.items.isEmpty { + if let view = views.views[stickersKey] as? OrderedItemListView { return view.items } else { return nil @@ -897,6 +897,25 @@ private final class DemoSheetContent: CombinedComponent { ) ) + availableItems[.animatedEmoji] = DemoPagerComponent.Item( + AnyComponentWithIdentity( + id: PremiumDemoScreen.Subject.animatedEmoji, + component: AnyComponent( + PageComponent( + content: AnyComponent(PhoneDemoComponent( + context: component.context, + position: .bottom, + videoFile: configuration.videos["animated_emoji"], + decoration: .emoji + )), + title: strings.Premium_AnimatedEmoji, + text: strings.Premium_AnimatedEmojiInfo, + textColor: textColor + ) + ) + ) + ) + var items: [DemoPagerComponent.Item] = component.order.compactMap { availableItems[$0] } let index: Int switch component.source { @@ -975,6 +994,9 @@ private final class DemoSheetContent: CombinedComponent { buttonAnimationName = "premium_unlock" case .noAds: buttonText = strings.Premium_NoAds_Proceed + case .animatedEmoji: + buttonText = strings.Premium_AnimatedEmoji_Proceed + buttonAnimationName = "premium_unlock" default: buttonText = strings.Common_OK } @@ -1146,6 +1168,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer { case profileBadge case animatedUserpics case appIcons + case animatedEmoji } public enum Source: Equatable { diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift new file mode 100644 index 0000000000..bb59828aab --- /dev/null +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -0,0 +1,1345 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import SwiftSignalKit +import Postbox +import TelegramCore +import TelegramPresentationData +import PresentationDataUtils +import ViewControllerComponent +import AccountContext +import SolidRoundedButtonComponent +import MultilineTextComponent +import BundleIconComponent +import SolidRoundedButtonComponent +import Markdown +import InAppPurchaseManager +import ConfettiEffect +import TextFormat +import CheckNode + +private final class ProductGroupComponent: Component { + public final class Item: Equatable { + public let content: AnyComponentWithIdentity + public let action: () -> Void + + public init(_ content: AnyComponentWithIdentity, action: @escaping () -> Void) { + self.content = content + self.action = action + } + + public static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs.content != rhs.content { + return false + } + + return true + } + } + + let items: [Item] + let backgroundColor: UIColor + let selectionColor: UIColor + + init( + items: [Item], + backgroundColor: UIColor, + selectionColor: UIColor + ) { + self.items = items + self.backgroundColor = backgroundColor + self.selectionColor = selectionColor + } + + public static func ==(lhs: ProductGroupComponent, rhs: ProductGroupComponent) -> Bool { + if lhs.items != rhs.items { + return false + } + if lhs.backgroundColor != rhs.backgroundColor { + return false + } + if lhs.selectionColor != rhs.selectionColor { + return false + } + return true + } + + public final class View: UIView { + private var buttonViews: [AnyHashable: HighlightTrackingButton] = [:] + private var itemViews: [AnyHashable: ComponentHostView] = [:] + + private var component: ProductGroupComponent? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func buttonPressed(_ sender: HighlightTrackingButton) { + guard let component = self.component else { + return + } + + if let (id, _) = self.buttonViews.first(where: { $0.value === sender }), let item = component.items.first(where: { $0.content.id == id }) { + item.action() + } + } + + func update(component: ProductGroupComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let spacing: CGFloat = 16.0 + var size = CGSize(width: availableSize.width, height: 0.0) + + var validIds: [AnyHashable] = [] + + var i = 0 + for item in component.items { + validIds.append(item.content.id) + + let buttonView: HighlightTrackingButton + let itemView: ComponentHostView + var itemTransition = transition + + if let current = self.buttonViews[item.content.id] { + buttonView = current + } else { + buttonView = HighlightTrackingButton() + buttonView.clipsToBounds = true + buttonView.layer.cornerRadius = 10.0 + if #available(iOS 13.0, *) { + buttonView.layer.cornerCurve = .continuous + } + buttonView.isMultipleTouchEnabled = false + buttonView.isExclusiveTouch = true + buttonView.addTarget(self, action: #selector(self.buttonPressed(_:)), for: .touchUpInside) + self.buttonViews[item.content.id] = buttonView + self.addSubview(buttonView) + } + buttonView.backgroundColor = component.backgroundColor + + if let current = self.itemViews[item.content.id] { + itemView = current + } else { + itemTransition = transition.withAnimation(.none) + itemView = ComponentHostView() + self.itemViews[item.content.id] = itemView + self.addSubview(itemView) + } + let itemSize = itemView.update( + transition: itemTransition, + component: item.content.component, + environment: {}, + containerSize: CGSize(width: size.width, height: .greatestFiniteMagnitude) + ) + + let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: size.height), size: itemSize) + buttonView.frame = CGRect(origin: itemFrame.origin, size: CGSize(width: availableSize.width, height: itemSize.height + UIScreenPixel)) + itemView.frame = CGRect(origin: CGPoint(x: itemFrame.minX, y: itemFrame.minY + floor((itemFrame.height - itemSize.height) / 2.0)), size: itemSize) + itemView.isUserInteractionEnabled = false + + buttonView.highligthedChanged = { [weak buttonView] highlighted in + if highlighted { + buttonView?.backgroundColor = component.selectionColor + } else { + UIView.animate(withDuration: 0.3, animations: { + buttonView?.backgroundColor = component.backgroundColor + }) + } + } + + size.height += itemSize.height + spacing + + i += 1 + } + + size.height -= spacing + + var removeIds: [AnyHashable] = [] + for (id, itemView) in self.itemViews { + if !validIds.contains(id) { + removeIds.append(id) + itemView.removeFromSuperview() + } + } + for id in removeIds { + self.itemViews.removeValue(forKey: id) + } + + self.component = component + + return size + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +private final class GiftComponent: CombinedComponent { + let title: String + let totalPrice: String + let perMonthPrice: String + let discount: String + let selected: Bool + let primaryTextColor: UIColor + let secondaryTextColor: UIColor + let accentColor: UIColor + let checkForegroundColor: UIColor + let checkBorderColor: UIColor + + init( + title: String, + totalPrice: String, + perMonthPrice: String, + discount: String, + selected: Bool, + primaryTextColor: UIColor, + secondaryTextColor: UIColor, + accentColor: UIColor, + checkForegroundColor: UIColor, + checkBorderColor: UIColor + ) { + self.title = title + self.totalPrice = totalPrice + self.perMonthPrice = perMonthPrice + self.discount = discount + self.selected = selected + self.primaryTextColor = primaryTextColor + self.secondaryTextColor = secondaryTextColor + self.accentColor = accentColor + self.checkForegroundColor = checkForegroundColor + self.checkBorderColor = checkBorderColor + } + + static func ==(lhs: GiftComponent, rhs: GiftComponent) -> Bool { + if lhs.title != rhs.title { + return false + } + if lhs.totalPrice != rhs.totalPrice { + return false + } + if lhs.perMonthPrice != rhs.perMonthPrice { + return false + } + if lhs.discount != rhs.discount { + return false + } + if lhs.selected != rhs.selected { + return false + } + if lhs.primaryTextColor != rhs.primaryTextColor { + return false + } + if lhs.secondaryTextColor != rhs.secondaryTextColor { + return false + } + if lhs.accentColor != rhs.accentColor { + return false + } + if lhs.checkForegroundColor != rhs.checkForegroundColor { + return false + } + if lhs.checkBorderColor != rhs.checkBorderColor { + return false + } + return true + } + + static var body: Body { + let check = Child(CheckComponent.self) + let title = Child(MultilineTextComponent.self) + let discountBackground = Child(RoundedRectangle.self) + let discount = Child(MultilineTextComponent.self) + let subtitle = Child(MultilineTextComponent.self) + let label = Child(MultilineTextComponent.self) + let selection = Child(RoundedRectangle.self) + + return { context in + let component = context.component + + let insets = UIEdgeInsets(top: 9.0, left: 62.0, bottom: 12.0, right: 16.0) + + let spacing: CGFloat = 2.0 + + let label = label.update( + component: MultilineTextComponent( + text: .plain( + NSAttributedString( + string: component.totalPrice, + font: Font.regular(17), + textColor: component.secondaryTextColor + ) + ), + maximumNumberOfLines: 1 + ), + availableSize: context.availableSize, + transition: context.transition + ) + + let title = title.update( + component: MultilineTextComponent( + text: .plain( + NSAttributedString( + string: component.title, + font: Font.regular(17), + textColor: component.primaryTextColor + ) + ), + maximumNumberOfLines: 1 + ), + availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right - label.size.width, height: context.availableSize.height), + transition: context.transition + ) + + let discountSize: CGSize + if !component.discount.isEmpty { + let discount = discount.update( + component: MultilineTextComponent( + text: .plain( + NSAttributedString( + string: component.discount, + font: Font.with(size: 14.0, design: .round, weight: .semibold, traits: []), + textColor: .white + ) + ), + maximumNumberOfLines: 1 + ), + availableSize: context.availableSize, + transition: context.transition + ) + + discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0) + + let discountBackground = discountBackground.update( + component: RoundedRectangle( + color: component.accentColor, + cornerRadius: 5.0 + ), + availableSize: discountSize, + transition: context.transition + ) + + context.add(discountBackground + .position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0)) + ) + + context.add(discount + .position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0)) + ) + } else { + discountSize = CGSize(width: 0.0, height: 18.0) + } + + let subtitle = subtitle.update( + component: MultilineTextComponent( + text: .plain( + NSAttributedString( + string: component.perMonthPrice, + font: Font.regular(13), + textColor: component.secondaryTextColor + ) + ), + maximumNumberOfLines: 1 + ), + availableSize: CGSize(width: context.availableSize.width - insets.left - insets.right - label.size.width - discountSize.width, height: context.availableSize.height), + transition: context.transition + ) + + let check = check.update( + component: CheckComponent( + theme: CheckComponent.Theme( + backgroundColor: component.accentColor, + strokeColor: component.checkForegroundColor, + borderColor: component.checkBorderColor, + overlayBorder: false, + hasInset: false, + hasShadow: false + ), + selected: component.selected + ), + availableSize: context.availableSize, + transition: context.transition + ) + + context.add(title + .position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0)) + ) + + context.add(subtitle + .position(CGPoint(x: insets.left + (discountSize.width.isZero ? 0.0 : discountSize.width + 7.0) + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0)) + ) + + let size = CGSize(width: context.availableSize.width, height: insets.top + title.size.height + spacing + subtitle.size.height + insets.bottom) + let distance = context.availableSize.width - insets.left - insets.right - label.size.width - subtitle.size.width - discountSize.width - 7.0 + + let labelOriginY: CGFloat + if distance > 8.0 { + labelOriginY = size.height / 2.0 + } else { + labelOriginY = insets.top + title.size.height / 2.0 + } + + context.add(label + .position(CGPoint(x: context.availableSize.width - insets.right - label.size.width / 2.0, y: labelOriginY)) + ) + + context.add(check + .position(CGPoint(x: 20.0 + check.size.width / 2.0, y: size.height / 2.0)) + ) + + if component.selected { + let selection = selection.update( + component: RoundedRectangle( + color: component.accentColor, + cornerRadius: 10.0, + stroke: 2.0 + ), + availableSize: size, + transition: context.transition + ) + context.add(selection + .position(CGPoint(x: size.width / 2.0, y: size.height / 2.0)) + ) + } + + return size + } + } +} + +private final class CheckComponent: Component { + struct Theme: Equatable { + public let backgroundColor: UIColor + public let strokeColor: UIColor + public let borderColor: UIColor + public let overlayBorder: Bool + public let hasInset: Bool + public let hasShadow: Bool + public let filledBorder: Bool + public let borderWidth: CGFloat? + + public init(backgroundColor: UIColor, strokeColor: UIColor, borderColor: UIColor, overlayBorder: Bool, hasInset: Bool, hasShadow: Bool, filledBorder: Bool = false, borderWidth: CGFloat? = nil) { + self.backgroundColor = backgroundColor + self.strokeColor = strokeColor + self.borderColor = borderColor + self.overlayBorder = overlayBorder + self.hasInset = hasInset + self.hasShadow = hasShadow + self.filledBorder = filledBorder + self.borderWidth = borderWidth + } + + var checkNodeTheme: CheckNodeTheme { + return CheckNodeTheme( + backgroundColor: self.backgroundColor, + strokeColor: self.strokeColor, + borderColor: self.borderColor, + overlayBorder: self.overlayBorder, + hasInset: self.hasInset, + hasShadow: self.hasShadow, + filledBorder: self.filledBorder, + borderWidth: self.borderWidth + ) + } + } + + let theme: Theme + let selected: Bool + + init( + theme: Theme, + selected: Bool + ) { + self.theme = theme + self.selected = selected + } + + static func ==(lhs: CheckComponent, rhs: CheckComponent) -> Bool { + if lhs.theme != rhs.theme { + return false + } + if lhs.selected != rhs.selected { + return false + } + return true + } + + final class View: UIView { + private var currentValue: CGFloat? + private var animator: DisplayLinkAnimator? + + private var checkLayer: CheckLayer { + return self.layer as! CheckLayer + } + + override class var layerClass: AnyClass { + return CheckLayer.self + } + + init() { + super.init(frame: CGRect()) + } + + required init?(coder aDecoder: NSCoder) { + preconditionFailure() + } + + + func update(component: CheckComponent, availableSize: CGSize, transition: Transition) -> CGSize { + self.checkLayer.setSelected(component.selected, animated: true) + self.checkLayer.theme = component.theme.checkNodeTheme + + return CGSize(width: 22.0, height: 22.0) + } + } + + func makeView() -> View { + return View() + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} + +private final class PremiumGiftScreenContentComponent: CombinedComponent { + typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment) + + let context: AccountContext + let peer: EnginePeer? + let products: [PremiumGiftProduct]? + let selectedProductId: String? + + let present: (ViewController) -> Void + let selectProduct: (String) -> Void + + init(context: AccountContext, peer: EnginePeer?, products: [PremiumGiftProduct]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) { + self.context = context + self.peer = peer + self.products = products + self.selectedProductId = selectedProductId + self.present = present + self.selectProduct = selectProduct + } + + static func ==(lhs: PremiumGiftScreenContentComponent, rhs: PremiumGiftScreenContentComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.peer != rhs.peer { + return false + } + if lhs.products != rhs.products { + return false + } + if lhs.selectedProductId != rhs.selectedProductId { + return false + } + + return true + } + + static var body: Body { + let overscroll = Child(Rectangle.self) + let fade = Child(RoundedRectangle.self) + let text = Child(MultilineTextComponent.self) + let section = Child(ProductGroupComponent.self) + + return { context in + let sideInset: CGFloat = 16.0 + + let component = context.component + + let scrollEnvironment = context.environment[ScrollChildEnvironment.self].value + let environment = context.environment[ViewControllerComponentContainer.Environment.self].value + + let theme = environment.theme + let strings = environment.strings + + let availableWidth = context.availableSize.width + let sideInsets = sideInset * 2.0 + environment.safeInsets.left + environment.safeInsets.right + var size = CGSize(width: context.availableSize.width, height: 0.0) + + let overscroll = overscroll.update( + component: Rectangle(color: theme.list.plainBackgroundColor), + availableSize: CGSize(width: context.availableSize.width, height: 1000), + transition: context.transition + ) + context.add(overscroll + .position(CGPoint(x: overscroll.size.width / 2.0, y: -overscroll.size.height / 2.0)) + ) + + let fade = fade.update( + component: RoundedRectangle( + colors: [ + theme.list.plainBackgroundColor, + theme.list.blocksBackgroundColor + ], + cornerRadius: 0.0, + gradientDirection: .vertical + ), + availableSize: CGSize(width: availableWidth, height: 300), + transition: context.transition + ) + context.add(fade + .position(CGPoint(x: fade.size.width / 2.0, y: fade.size.height / 2.0)) + ) + + size.height += 183.0 + 10.0 + environment.navigationHeight - 56.0 + + let textColor = theme.list.itemPrimaryTextColor + let subtitleColor = theme.list.itemSecondaryTextColor + + let textFont = Font.regular(15.0) + let boldTextFont = Font.semibold(15.0) + + let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: textColor), linkAttribute: { _ in + return nil + }) + let text = text.update( + component: MultilineTextComponent( + text: .markdown( + text: strings.Premium_Gift_Description(component.peer?.compactDisplayTitle ?? "").string, + attributes: markdownAttributes + ), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.2 + ), + environment: {}, + availableSize: CGSize(width: availableWidth - sideInsets, height: 240.0), + transition: context.transition + ) + context.add(text + .position(CGPoint(x: size.width / 2.0, y: size.height + text.size.height / 2.0)) + ) + size.height += text.size.height + size.height += 21.0 + + var items: [ProductGroupComponent.Item] = [] + + let gradientColors: [UIColor] = [ + UIColor(rgb: 0x8e77ff), + UIColor(rgb: 0x9a6fff), + UIColor(rgb: 0xb36eee) + ] + + var i = 0 + if let products = component.products { + let shortestOptionPrice: Int64 + if let product = products.last { + shortestOptionPrice = Int64(Float(product.storeProduct.priceCurrencyAndAmount.amount) / Float(product.months)) + } else { + shortestOptionPrice = 1 + } + + for product in products { + let giftTitle: String + if product.months == 12 { + giftTitle = strings.Premium_Gift_Years(1) + } else { + giftTitle = strings.Premium_Gift_Months(product.months) + } + + let discountValue = Int((1.0 - Float(product.storeProduct.priceCurrencyAndAmount.amount) / Float(product.months) / Float(shortestOptionPrice)) * 100.0) + let discount: String + if discountValue > 0 { + discount = "-\(discountValue)%" + } else { + discount = "" + } + + items.append(ProductGroupComponent.Item( + AnyComponentWithIdentity( + id: product.id, + component: AnyComponent( + GiftComponent( + title: giftTitle, + totalPrice: product.price, + perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth).string, + discount: discount, + selected: product.id == component.selectedProductId, + primaryTextColor: textColor, + secondaryTextColor: subtitleColor, + accentColor: gradientColors[i], + checkForegroundColor: environment.theme.list.itemCheckColors.foregroundColor, + checkBorderColor: environment.theme.list.itemCheckColors.strokeColor + ) + ) + ), + action: { + component.selectProduct(product.id) + }) + ) + i += 1 + } + } + + let section = section.update( + component: ProductGroupComponent( + items: items, + backgroundColor: environment.theme.list.itemBlocksBackgroundColor, + selectionColor: environment.theme.list.itemHighlightedBackgroundColor + ), + environment: {}, + availableSize: CGSize(width: availableWidth - sideInsets, height: .greatestFiniteMagnitude), + transition: context.transition + ) + context.add(section + .position(CGPoint(x: availableWidth / 2.0, y: size.height + section.size.height / 2.0)) + .clipsToBounds(true) + .cornerRadius(10.0) + ) + size.height += section.size.height + size.height += 23.0 + + + size.height += 10.0 + size.height += scrollEnvironment.insets.bottom + + return size + } + } +} + +private struct PremiumGiftProduct: Equatable { + let giftOption: CachedPremiumGiftOption + let storeProduct: InAppPurchaseManager.Product + + var id: String { + return self.storeProduct.id + } + + var months: Int32 { + return self.giftOption.months + } + + var price: String { + return self.storeProduct.price + } + + var pricePerMonth: String { + return self.storeProduct.pricePerMonth(Int(self.months)) + } +} + +private final class PremiumGiftScreenComponent: CombinedComponent { + typealias EnvironmentType = ViewControllerComponentContainer.Environment + + let context: AccountContext + let peerId: PeerId + let options: [CachedPremiumGiftOption] + let updateInProgress: (Bool) -> Void + let present: (ViewController) -> Void + let push: (ViewController) -> Void + let completion: (Int32) -> Void + + init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption], updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) { + self.context = context + self.peerId = peerId + self.options = options + self.updateInProgress = updateInProgress + self.present = present + self.push = push + self.completion = completion + } + + static func ==(lhs: PremiumGiftScreenComponent, rhs: PremiumGiftScreenComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.peerId != rhs.peerId { + return false + } + if lhs.options != rhs.options { + return false + } + return true + } + + final class State: ComponentState { + private let context: AccountContext + private let peerId: PeerId + private let options: [CachedPremiumGiftOption] + private let updateInProgress: (Bool) -> Void + private let present: (ViewController) -> Void + private let completion: (Int32) -> Void + + var topContentOffset: CGFloat? + var bottomContentOffset: CGFloat? + + var hasIdleAnimations = true + + var inProgress = false + + var peer: EnginePeer? + var products: [PremiumGiftProduct]? + var selectedProductId: String? + + private var disposable: Disposable? + private var paymentDisposable = MetaDisposable() + private var activationDisposable = MetaDisposable() + + init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption], updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) { + self.context = context + self.peerId = peerId + self.options = options + self.updateInProgress = updateInProgress + self.present = present + self.completion = completion + + super.init() + + let availableProducts: Signal<[InAppPurchaseManager.Product], NoError> + if let inAppPurchaseManager = context.inAppPurchaseManager { + availableProducts = inAppPurchaseManager.availableProducts + } else { + availableProducts = .single([]) + } + + self.disposable = combineLatest( + queue: Queue.mainQueue(), + availableProducts, + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + ).start(next: { [weak self] products, peer in + if let strongSelf = self { + + var gifts: [PremiumGiftProduct] = [] + for option in strongSelf.options { + if let product = products.first(where: { $0.id == option.storeProductId }), !product.isSubscription { + gifts.append(PremiumGiftProduct(giftOption: option, storeProduct: product)) + } + } + + strongSelf.products = gifts + if strongSelf.selectedProductId == nil { + strongSelf.selectedProductId = strongSelf.products?.first?.id + } + strongSelf.peer = peer + strongSelf.updated(transition: .immediate) + } + }) + } + + deinit { + self.disposable?.dispose() + self.paymentDisposable.dispose() + self.activationDisposable.dispose() + } + + func selectProduct(id: String) { + self.selectedProductId = id + self.updated(transition: .immediate) + } + + func buy() { + guard let inAppPurchaseManager = self.context.inAppPurchaseManager, !self.inProgress else { + return + } + + guard let product = self.products?.first(where: { $0.id == self.selectedProductId }) else { + return + } + let (currency, amount) = product.storeProduct.priceCurrencyAndAmount + let duration = product.months + +// addAppLogEvent(postbox: self.context.account.postbox, type: "premium.promo_screen_accept") + + self.inProgress = true + self.updateInProgress(true) + self.updated(transition: .immediate) + + let _ = (self.context.engine.payments.canPurchasePremium(purpose: .gift(peerId: self.peerId, currency: currency, amount: amount)) + |> deliverOnMainQueue).start(next: { [weak self] available in + if let strongSelf = self { + if available { + strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product.storeProduct, targetPeerId: strongSelf.peerId) + |> deliverOnMainQueue).start(next: { [weak self] status in + if let strongSelf = self, case .purchased = status { + strongSelf.activationDisposable.set((strongSelf.context.account.postbox.peerView(id: strongSelf.context.account.peerId) + |> castError(AssignAppStoreTransactionError.self) + |> take(until: { view in + if let peer = view.peers[view.peerId], peer.isPremium { + return SignalTakeAction(passthrough: false, complete: true) + } else { + return SignalTakeAction(passthrough: false, complete: false) + } + }) + |> mapToSignal { _ -> Signal in + return .never() + } + |> timeout(15.0, queue: Queue.mainQueue(), alternate: .fail(.timeout)) + |> deliverOnMainQueue).start(error: { [weak self] _ in + if let strongSelf = self { + strongSelf.inProgress = false + strongSelf.updateInProgress(false) + + strongSelf.updated(transition: .immediate) + +// addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail") + + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) + strongSelf.present(alertController) + } + }, completed: { [weak self] in + if let strongSelf = self { + Queue.mainQueue().after(2.0) { + let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start() + strongSelf.inProgress = false + strongSelf.updateInProgress(false) + + strongSelf.updated(transition: .easeInOut(duration: 0.25)) + strongSelf.completion(duration) + } + } + })) + } + }, error: { [weak self] error in + if let strongSelf = self { + strongSelf.inProgress = false + strongSelf.updateInProgress(false) + strongSelf.updated(transition: .immediate) + + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + var errorText: String? + switch error { + case .generic: + errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + case .network: + errorText = presentationData.strings.Premium_Purchase_ErrorNetwork + case .notAllowed: + errorText = presentationData.strings.Premium_Purchase_ErrorNotAllowed + case .cantMakePayments: + errorText = presentationData.strings.Premium_Purchase_ErrorCantMakePayments + case .assignFailed: + errorText = presentationData.strings.Premium_Purchase_ErrorUnknown + case .cancelled: + break + } + + if let errorText = errorText { +// addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail") + + let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]) + strongSelf.present(alertController) + } + } + })) + } else { + strongSelf.inProgress = false + strongSelf.updateInProgress(false) + strongSelf.updated(transition: .immediate) + } + } + }) + } + + func updateIsFocused(_ isFocused: Bool) { + self.hasIdleAnimations = !isFocused + self.updated(transition: .immediate) + } + } + + func makeState() -> State { + return State(context: self.context, peerId: self.peerId, options: self.options, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion) + } + + static var body: Body { + let background = Child(Rectangle.self) + let scrollContent = Child(ScrollComponent.self) + let star = Child(GiftAvatarComponent.self) + let topPanel = Child(BlurredRectangle.self) + let topSeparator = Child(Rectangle.self) + let title = Child(MultilineTextComponent.self) + let bottomPanel = Child(BlurredRectangle.self) + let bottomSeparator = Child(Rectangle.self) + let button = Child(SolidRoundedButtonComponent.self) + let termsText = Child(MultilineTextComponent.self) + + return { context in + let environment = context.environment[EnvironmentType.self].value + let state = context.state + + let background = background.update(component: Rectangle(color: environment.theme.list.blocksBackgroundColor), environment: {}, availableSize: context.availableSize, transition: context.transition) + + var starIsVisible = true + if let topContentOffset = state.topContentOffset, topContentOffset >= 123.0 { + starIsVisible = false + } + + let topPanel = topPanel.update( + component: BlurredRectangle( + color: environment.theme.rootController.navigationBar.blurredBackgroundColor + ), + availableSize: CGSize(width: context.availableSize.width, height: environment.navigationHeight), + transition: context.transition + ) + + let topSeparator = topSeparator.update( + component: Rectangle( + color: environment.theme.rootController.navigationBar.separatorColor + ), + availableSize: CGSize(width: context.availableSize.width, height: UIScreenPixel), + transition: context.transition + ) + + let title = title.update( + component: MultilineTextComponent( + text: .plain(NSAttributedString(string: environment.strings.Premium_Gift_Title, font: Font.bold(28.0), textColor: environment.theme.rootController.navigationBar.primaryTextColor)), + horizontalAlignment: .center, + truncationType: .end, + maximumNumberOfLines: 1 + ), + availableSize: context.availableSize, + transition: context.transition + ) + + let bottomPanelPadding: CGFloat = 12.0 + let bottomInset: CGFloat = environment.safeInsets.bottom > 0.0 ? environment.safeInsets.bottom + 5.0 : bottomPanelPadding + let bottomPanelHeight: CGFloat = bottomPanelPadding + 50.0 + bottomInset + + let topInset: CGFloat = environment.navigationHeight - 56.0 + + context.add(background + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) + ) + + let scrollContent = scrollContent.update( + component: ScrollComponent( + content: AnyComponent(PremiumGiftScreenContentComponent( + context: context.component.context, + peer: state.peer, + products: state.products, + selectedProductId: state.selectedProductId, + present: context.component.present, + selectProduct: { [weak state] productId in + state?.selectProduct(id: productId) + } + )), + contentInsets: UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: bottomPanelHeight, right: 0.0), + contentOffsetUpdated: { [weak state] topContentOffset, bottomContentOffset in + state?.topContentOffset = topContentOffset + state?.bottomContentOffset = bottomContentOffset + Queue.mainQueue().justDispatch { + state?.updated(transition: .immediate) + } + }, + contentOffsetWillCommit: { targetContentOffset in + if targetContentOffset.pointee.y < 100.0 { + targetContentOffset.pointee = CGPoint(x: 0.0, y: 0.0) + } else if targetContentOffset.pointee.y < 123.0 { + targetContentOffset.pointee = CGPoint(x: 0.0, y: 123.0) + } + } + ), + environment: { environment }, + availableSize: context.availableSize, + transition: context.transition + ) + + context.add(scrollContent + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) + ) + + let topPanelAlpha: CGFloat + let titleOffset: CGFloat + let titleScale: CGFloat + let titleOffsetDelta = (topInset + 160.0) - (environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0) + let titleAlpha: CGFloat + + if let topContentOffset = state.topContentOffset { + topPanelAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0 + let topContentOffset = topContentOffset + max(0.0, min(1.0, topContentOffset / titleOffsetDelta)) * 10.0 + titleOffset = topContentOffset + let fraction = max(0.0, min(1.0, titleOffset / titleOffsetDelta)) + titleScale = 1.0 - fraction * 0.36 + titleAlpha = 1.0 + } else { + topPanelAlpha = 0.0 + titleScale = 1.0 + titleOffset = 0.0 + titleAlpha = 1.0 + } + + let star = star.update( + component: GiftAvatarComponent( + context: context.component.context, + peer: context.state.peer, + isVisible: starIsVisible, + hasIdleAnimations: state.hasIdleAnimations + ), + availableSize: CGSize(width: min(390.0, context.availableSize.width), height: 220.0), + transition: context.transition + ) + + context.add(star + .position(CGPoint(x: context.availableSize.width / 2.0, y: topInset + star.size.height / 2.0 - 30.0 - titleOffset * titleScale)) + .scale(titleScale) + ) + + context.add(topPanel + .position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height / 2.0)) + .opacity(topPanelAlpha) + ) + context.add(topSeparator + .position(CGPoint(x: context.availableSize.width / 2.0, y: topPanel.size.height)) + .opacity(topPanelAlpha) + ) + + context.add(title + .position(CGPoint(x: context.availableSize.width / 2.0, y: max(topInset + 160.0 - titleOffset, environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0))) + .scale(titleScale) + .opacity(titleAlpha) + ) + + let price: String? + if let products = state.products, let selectedProductId = state.selectedProductId, let product = products.first(where: { $0.id == selectedProductId }) { + price = product.price + } else { + price = nil + } + + let sideInset: CGFloat = 16.0 + let button = button.update( + component: SolidRoundedButtonComponent( + title: environment.strings.Premium_Gift_GiftSubscription(price ?? "—").string, + theme: SolidRoundedButtonComponent.Theme( + backgroundColor: UIColor(rgb: 0x8878ff), + backgroundColors: [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ], + foregroundColor: .white + ), + height: 50.0, + cornerRadius: 11.0, + gloss: true, + isLoading: state.inProgress, + action: { + state.buy() + } + ), + availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - environment.safeInsets.left - environment.safeInsets.right, height: 50.0), + transition: context.transition) + + let bottomPanel = bottomPanel.update( + component: BlurredRectangle( + color: environment.theme.rootController.tabBar.backgroundColor + ), + availableSize: CGSize(width: context.availableSize.width, height: bottomPanelPadding + button.size.height + bottomInset), + transition: context.transition + ) + + let bottomSeparator = bottomSeparator.update( + component: Rectangle( + color: environment.theme.rootController.tabBar.separatorColor + ), + availableSize: CGSize(width: context.availableSize.width, height: UIScreenPixel), + transition: context.transition + ) + + let bottomPanelAlpha: CGFloat + if let bottomContentOffset = state.bottomContentOffset { + bottomPanelAlpha = min(16.0, bottomContentOffset) / 16.0 + } else { + bottomPanelAlpha = 0.0 + } + + context.add(bottomPanel + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height - bottomPanel.size.height / 2.0)) + .opacity(bottomPanelAlpha) + .disappear(Transition.Disappear { view, transition, completion in + if case .none = transition.animation { + completion() + return + } + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: bottomPanel.size.height), duration: 0.2, removeOnCompletion: false, additive: true, completion: { _ in + completion() + }) + }) + ) + context.add(bottomSeparator + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height - bottomPanel.size.height)) + .opacity(bottomPanelAlpha) + .disappear(Transition.Disappear { view, transition, completion in + if case .none = transition.animation { + completion() + return + } + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: bottomPanel.size.height), duration: 0.2, removeOnCompletion: false, additive: true, completion: { _ in + completion() + }) + }) + ) + context.add(button + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height - bottomPanel.size.height + bottomPanelPadding + button.size.height / 2.0)) + .disappear(Transition.Disappear { view, transition, completion in + if case .none = transition.animation { + completion() + return + } + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: bottomPanel.size.height), duration: 0.2, removeOnCompletion: false, additive: true, completion: { _ in + completion() + }) + }) + ) + + if let _ = context.state.peer { + let accountContext = context.component.context + let present = context.component.present + + let sideInset: CGFloat = 16.0 + let textSideInset: CGFloat = 16.0 + let availableWidth = context.availableSize.width + let sideInsets = sideInset * 2.0 + environment.safeInsets.left + environment.safeInsets.right + + let termsFont = Font.regular(13.0) + let termsTextColor = environment.theme.list.freeTextColor + let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsFont, textColor: environment.theme.list.itemAccentColor), linkAttribute: { contents in + return (TelegramTextAttributes.URL, contents) + }) + + let termsString: MultilineTextComponent.TextContent = .markdown( + text: environment.strings.Premium_Gift_Info, + attributes: termsMarkdownAttributes + ) + + let termsText = termsText.update( + component: MultilineTextComponent( + text: termsString, + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.0, + highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.3), + highlightAction: { attributes in + if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] { + return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL) + } else { + return nil + } + }, + tapAction: { attributes, _ in + if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { + let controller = PremiumIntroScreen(context: accountContext, source: .giftTerms) + present(controller) + } + } + ), + environment: {}, + availableSize: CGSize(width: availableWidth - sideInsets - textSideInset * 2.0, height: .greatestFiniteMagnitude), + transition: context.transition + ) + context.add(termsText + .position(CGPoint(x: sideInset + environment.safeInsets.left + textSideInset + termsText.size.width / 2.0, y: context.availableSize.height - bottomPanel.size.height - termsText.size.height)) + ) + } + + return context.availableSize + } + } +} + +public final class PremiumGiftScreen: ViewControllerComponentContainer { + fileprivate let context: AccountContext + + private var didSetReady = false + private let _ready = Promise() + public override var ready: Promise { + return self._ready + } + + public weak var sourceView: UIView? + public weak var containerView: UIView? + public var animationColor: UIColor? + + public init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption]) { + self.context = context + + var updateInProgressImpl: ((Bool) -> Void)? + var pushImpl: ((ViewController) -> Void)? +// var presentImpl: ((ViewController) -> Void)? + var completionImpl: ((Int32) -> Void)? + super.init(context: context, component: PremiumGiftScreenComponent( + context: context, + peerId: peerId, + options: options, + updateInProgress: { inProgress in + updateInProgressImpl?(inProgress) + }, + present: { c in + pushImpl?(c) + }, + push: { c in + pushImpl?(c) + }, + completion: { duration in + completionImpl?(duration) + } + ), navigationBarAppearance: .transparent) + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let cancelItem = UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)) + self.navigationItem.setLeftBarButton(cancelItem, animated: false) + self.navigationPresentation = .modal + + updateInProgressImpl = { [weak self] inProgress in + if let strongSelf = self { + strongSelf.navigationItem.leftBarButtonItem?.isEnabled = !inProgress + strongSelf.view.disablesInteractiveTransitionGestureRecognizer = inProgress + strongSelf.view.disablesInteractiveModalDismiss = inProgress + } + } + + pushImpl = { [weak self] c in + self?.push(c) + } + + completionImpl = { [weak self] duration in + if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) } + for controller in controllers.reversed() { + if let chatController = controller as? ChatController, case .peer(id: peerId) = chatController.chatLocation { + chatController.hintPlayNextOutgoingGift() + break + } + } + navigationController.setViewControllers(controllers, animated: true) + } + } + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func cancelPressed() { + self.dismiss() + } + + public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + + if !self.didSetReady { + self.didSetReady = true + if let view = self.node.hostView.findTaggedView(tag: GiftAvatarComponent.View.Tag()) as? GiftAvatarComponent.View { + self._ready.set(view.ready) + } else { + self._ready.set(.single(true)) + } + } + } +} diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 69301eaacd..b0305e0722 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -11,7 +11,6 @@ import ViewControllerComponent import AccountContext import SolidRoundedButtonComponent import MultilineTextComponent -import PrefixSectionGroupComponent import BundleIconComponent import SolidRoundedButtonComponent import Markdown @@ -37,10 +36,13 @@ public enum PremiumSource: Equatable { case accounts case about case appIcons + case animatedEmoji case deeplink(String?) case profile(PeerId) + case gift(from: PeerId, to: PeerId, duration: Int32) + case giftTerms - var identifier: String { + var identifier: String? { switch self { case .settings: return "settings" @@ -72,8 +74,12 @@ public enum PremiumSource: Equatable { return "double_limits__accounts" case .about: return "double_limits__about" + case .animatedEmoji: + return "animated_emoji" case let .profile(id): return "profile__\(id.id._internalGetInt64Value())" + case .gift, .giftTerms: + return nil case let .deeplink(reference): if let reference = reference { return "deeplink_\(reference)" @@ -96,6 +102,7 @@ enum PremiumPerk: CaseIterable { case profileBadge case animatedUserpics case appIcons + case animatedEmoji static var allCases: [PremiumPerk] { return [ @@ -109,7 +116,8 @@ enum PremiumPerk: CaseIterable { .advancedChatManagement, .profileBadge, .animatedUserpics, - .appIcons + .appIcons, + .animatedEmoji ] } @@ -147,6 +155,8 @@ enum PremiumPerk: CaseIterable { return "animated_userpics" case .appIcons: return "app_icon" + case .animatedEmoji: + return "animated_emoji" } } @@ -174,6 +184,8 @@ enum PremiumPerk: CaseIterable { return strings.Premium_Avatar case .appIcons: return strings.Premium_AppIcon + case .animatedEmoji: + return strings.Premium_AnimatedEmoji } } @@ -201,6 +213,8 @@ enum PremiumPerk: CaseIterable { return strings.Premium_AvatarInfo case .appIcons: return strings.Premium_AppIconInfo + case .animatedEmoji: + return strings.Premium_AnimatedEmojiInfo } } @@ -228,6 +242,8 @@ enum PremiumPerk: CaseIterable { return "Premium/Perk/Avatar" case .appIcons: return "Premium/Perk/AppIcon" + case .animatedEmoji: + return "Premium/Perk/Emoji" } } } @@ -242,6 +258,7 @@ private struct PremiumIntroConfiguration { .noAds, .uniqueReactions, .premiumStickers, + .animatedEmoji, .advancedChatManagement, .profileBadge, .animatedUserpics, @@ -274,9 +291,6 @@ private struct PremiumIntroConfiguration { if perks.count < 4 { perks = PremiumIntroConfiguration.defaultValue.perks } - if !perks.contains(.appIcons) { - perks.append(.appIcons) - } return PremiumIntroConfiguration(perks: perks) } else { return .defaultValue @@ -470,135 +484,6 @@ private final class SectionGroupComponent: Component { } } - -private final class ScrollChildEnvironment: Equatable { - public let insets: UIEdgeInsets - - public init(insets: UIEdgeInsets) { - self.insets = insets - } - - public static func ==(lhs: ScrollChildEnvironment, rhs: ScrollChildEnvironment) -> Bool { - if lhs.insets != rhs.insets { - return false - } - - return true - } -} - -private final class ScrollComponent: Component { - public typealias EnvironmentType = ChildEnvironment - - public let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)> - public let contentInsets: UIEdgeInsets - public let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void - public let contentOffsetWillCommit: (UnsafeMutablePointer) -> Void - - public init( - content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>, - contentInsets: UIEdgeInsets, - contentOffsetUpdated: @escaping (_ top: CGFloat, _ bottom: CGFloat) -> Void, - contentOffsetWillCommit: @escaping (UnsafeMutablePointer) -> Void - ) { - self.content = content - self.contentInsets = contentInsets - self.contentOffsetUpdated = contentOffsetUpdated - self.contentOffsetWillCommit = contentOffsetWillCommit - } - - public static func ==(lhs: ScrollComponent, rhs: ScrollComponent) -> Bool { - if lhs.content != rhs.content { - return false - } - if lhs.contentInsets != rhs.contentInsets { - return false - } - - return true - } - - public final class View: UIScrollView, UIScrollViewDelegate { - private var component: ScrollComponent? - private let contentView: ComponentHostView<(ChildEnvironment, ScrollChildEnvironment)> - - override init(frame: CGRect) { - self.contentView = ComponentHostView() - - super.init(frame: frame) - - if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { - self.contentInsetAdjustmentBehavior = .never - } - self.delegate = self - self.showsVerticalScrollIndicator = false - self.showsHorizontalScrollIndicator = false - self.canCancelContentTouches = true - - self.addSubview(self.contentView) - } - - public override func touchesShouldCancel(in view: UIView) -> Bool { - return true - } - - private var ignoreDidScroll = false - public func scrollViewDidScroll(_ scrollView: UIScrollView) { - guard let component = self.component, !self.ignoreDidScroll else { - return - } - let topOffset = scrollView.contentOffset.y - let bottomOffset = max(0.0, scrollView.contentSize.height - scrollView.contentOffset.y - scrollView.frame.height) - component.contentOffsetUpdated(topOffset, bottomOffset) - } - - public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { - guard let component = self.component, !self.ignoreDidScroll else { - return - } - component.contentOffsetWillCommit(targetContentOffset) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - func update(component: ScrollComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - let contentSize = self.contentView.update( - transition: transition, - component: component.content, - environment: { - environment[ChildEnvironment.self] - ScrollChildEnvironment(insets: component.contentInsets) - }, - containerSize: CGSize(width: availableSize.width, height: .greatestFiniteMagnitude) - ) - transition.setFrame(view: self.contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil) - - if self.contentSize != contentSize { - self.ignoreDidScroll = true - self.contentSize = contentSize - self.ignoreDidScroll = false - } - if self.scrollIndicatorInsets != component.contentInsets { - self.scrollIndicatorInsets = component.contentInsets - } - - self.component = component - - return availableSize - } - } - - public func makeView() -> View { - return View(frame: CGRect()) - } - - public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) - } -} - private final class PerkComponent: CombinedComponent { let iconName: String let iconBackgroundColors: [UIColor] @@ -825,22 +710,24 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { strongSelf.promoConfiguration = promoConfiguration strongSelf.updated(transition: .immediate) - var jsonString: String = "{" - jsonString += "\"source\": \"\(source.identifier)\"," - - jsonString += "\"data\": {\"premium_promo_order\":[" - var isFirst = true - for perk in strongSelf.configuration.perks { - if !isFirst { - jsonString += "," + if let identifier = source.identifier { + var jsonString: String = "{" + jsonString += "\"source\": \"\(identifier)\"," + + jsonString += "\"data\": {\"premium_promo_order\":[" + var isFirst = true + for perk in strongSelf.configuration.perks { + if !isFirst { + jsonString += "," + } + isFirst = false + jsonString += "\"\(perk.identifier)\"" + } + jsonString += "]}}" + + if let data = jsonString.data(using: .utf8), let json = JSON(data: data) { + addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_show", data: json) } - isFirst = false - jsonString += "\"\(perk.identifier)\"" - } - jsonString += "]}}" - - if let data = jsonString.data(using: .utf8), let json = JSON(data: data) { - addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_show", data: json) } for (_, video) in promoConfiguration.videos { @@ -944,8 +831,18 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { let boldTextFont = Font.semibold(15.0) let textString: String - if let _ = context.component.otherPeerName { + if case .giftTerms = context.component.source { textString = strings.Premium_PersonalDescription + } else if let _ = context.component.otherPeerName { + if case let .gift(fromId, _, _) = context.component.source { + if fromId == context.component.context.account.peerId { + textString = strings.Premium_GiftedDescriptionYou + } else { + textString = strings.Premium_GiftedDescription + } + } else { + textString = strings.Premium_PersonalDescription + } } else if context.component.isPremium == true { textString = strings.Premium_SubscribedDescription } else { @@ -986,6 +883,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { UIColor(rgb: 0x7561EB), UIColor(rgb: 0x5A6EEE), UIColor(rgb: 0x548DFF), + UIColor(rgb: 0x54A3FF), UIColor(rgb: 0x54A3FF) ] @@ -1057,6 +955,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { demoSubject = .animatedUserpics case .appIcons: demoSubject = .appIcons + case .animatedEmoji: + demoSubject = .animatedEmoji } let controller = PremiumDemoScreen( @@ -1166,9 +1066,18 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { return (TelegramTextAttributes.URL, contents) }) + var isGiftView = false + if case let .gift(fromId, _, _) = context.component.source { + if fromId == context.component.context.account.peerId { + isGiftView = true + } + } + let termsString: MultilineTextComponent.TextContent - if let promoConfiguration = context.state.promoConfiguration { - let attributedString = stringWithAppliedEntities(promoConfiguration.status, entities: promoConfiguration.statusEntities, baseColor: termsTextColor, linkColor: environment.theme.list.itemAccentColor, baseFont: termsFont, linkFont: termsFont, boldFont: boldTermsFont, italicFont: italicTermsFont, boldItalicFont: boldItalicTermsFont, fixedFont: monospaceTermsFont, blockQuoteFont: termsFont) + if isGiftView { + termsString = .plain(NSAttributedString()) + } else if let promoConfiguration = context.state.promoConfiguration { + let attributedString = stringWithAppliedEntities(promoConfiguration.status, entities: promoConfiguration.statusEntities, baseColor: termsTextColor, linkColor: environment.theme.list.itemAccentColor, baseFont: termsFont, linkFont: termsFont, boldFont: boldTermsFont, italicFont: italicTermsFont, boldItalicFont: boldItalicTermsFont, fixedFont: monospaceTermsFont, blockQuoteFont: termsFont, message: nil) termsString = .plain(attributedString) } else { termsString = .markdown( @@ -1359,7 +1268,14 @@ private final class PremiumIntroScreenComponent: CombinedComponent { } let otherPeerName: Signal - if case let .profile(peerId) = source { + if case let .gift(fromPeerId, toPeerId, _) = source { + let otherPeerId = fromPeerId != context.account.peerId ? fromPeerId : toPeerId + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + otherPeerName = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: otherPeerId)) + |> map { peer -> String? in + return peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + } + } else if case let .profile(peerId) = source { let presentationData = context.sharedContext.currentPresentationData.with { $0 } otherPeerName = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) |> map { peer -> String? in @@ -1379,7 +1295,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { otherPeerName ).start(next: { [weak self] products, isPremium, otherPeerName in if let strongSelf = self { - strongSelf.premiumProduct = products.first + strongSelf.premiumProduct = products.first(where: { $0.isSubscription }) strongSelf.isPremium = isPremium strongSelf.otherPeerName = otherPeerName strongSelf.updated(transition: .immediate) @@ -1405,7 +1321,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { self.updateInProgress(true) self.updated(transition: .immediate) - let _ = (self.context.engine.payments.canPurchasePremium() + let _ = (self.context.engine.payments.canPurchasePremium(purpose: .subscription) |> deliverOnMainQueue).start(next: { [weak self] available in if let strongSelf = self { if available { @@ -1548,7 +1464,11 @@ private final class PremiumIntroScreenComponent: CombinedComponent { ) let titleString: String - if state.isPremium == true { + if case .giftTerms = context.component.source { + titleString = environment.strings.Premium_Title + } else if case .gift = context.component.source { + titleString = environment.strings.Premium_GiftedTitle + } else if state.isPremium == true { titleString = environment.strings.Premium_SubscribedTitle } else { titleString = environment.strings.Premium_Title @@ -1574,15 +1494,49 @@ private final class PremiumIntroScreenComponent: CombinedComponent { let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: accentColor), linkAttribute: { _ in return nil }) + + let secondaryTitleText: String + if let otherPeerName = state.otherPeerName { + if case .profile = context.component.source { + secondaryTitleText = environment.strings.Premium_PersonalTitle(otherPeerName).string + } else if case let .gift(fromPeerId, _, duration) = context.component.source { + if fromPeerId == context.component.context.account.peerId { + if duration == 12 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_12Month(otherPeerName).string + } else if duration == 6 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_6Month(otherPeerName).string + } else if duration == 3 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_3Month(otherPeerName).string + } else { + secondaryTitleText = "" + } + } else { + if duration == 12 { + secondaryTitleText = environment.strings.Premium_GiftedTitle_12Month(otherPeerName).string + } else if duration == 6 { + secondaryTitleText = environment.strings.Premium_GiftedTitle_6Month(otherPeerName).string + } else if duration == 3 { + secondaryTitleText = environment.strings.Premium_GiftedTitle_3Month(otherPeerName).string + } else { + secondaryTitleText = "" + } + } + } else { + secondaryTitleText = "" + } + } else { + secondaryTitleText = "" + } + let secondaryTitle = secondaryTitle.update( component: MultilineTextComponent( - text: .markdown(text: state.otherPeerName.flatMap({ environment.strings.Premium_PersonalTitle($0).string }) ?? "", attributes: markdownAttributes), + text: .markdown(text: secondaryTitleText, attributes: markdownAttributes), horizontalAlignment: .center, truncationType: .end, maximumNumberOfLines: 2, lineSpacing: 0.0 ), - availableSize: context.availableSize, + availableSize: CGSize(width: context.availableSize.width - 32.0, height: context.availableSize.width), transition: context.transition ) @@ -1687,8 +1641,15 @@ private final class PremiumIntroScreenComponent: CombinedComponent { .scale(titleScale) .opacity(max(0.0, 1.0 - titleAlpha * 1.8)) ) + + var isGiftView = false + if case let .gift(fromId, _, _) = context.component.source { + if fromId == context.component.context.account.peerId { + isGiftView = true + } + } - if state.isPremium == true { + if state.isPremium == true || isGiftView { } else { let sideInset: CGFloat = 16.0 diff --git a/submodules/PremiumUI/Sources/ScrollComponent.swift b/submodules/PremiumUI/Sources/ScrollComponent.swift new file mode 100644 index 0000000000..a0797ca1d0 --- /dev/null +++ b/submodules/PremiumUI/Sources/ScrollComponent.swift @@ -0,0 +1,132 @@ +import Foundation +import UIKit +import ComponentFlow +import Display + +final class ScrollChildEnvironment: Equatable { + public let insets: UIEdgeInsets + + public init(insets: UIEdgeInsets) { + self.insets = insets + } + + public static func ==(lhs: ScrollChildEnvironment, rhs: ScrollChildEnvironment) -> Bool { + if lhs.insets != rhs.insets { + return false + } + + return true + } +} + +final class ScrollComponent: Component { + public typealias EnvironmentType = ChildEnvironment + + public let content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)> + public let contentInsets: UIEdgeInsets + public let contentOffsetUpdated: (_ top: CGFloat, _ bottom: CGFloat) -> Void + public let contentOffsetWillCommit: (UnsafeMutablePointer) -> Void + + public init( + content: AnyComponent<(ChildEnvironment, ScrollChildEnvironment)>, + contentInsets: UIEdgeInsets, + contentOffsetUpdated: @escaping (_ top: CGFloat, _ bottom: CGFloat) -> Void, + contentOffsetWillCommit: @escaping (UnsafeMutablePointer) -> Void + ) { + self.content = content + self.contentInsets = contentInsets + self.contentOffsetUpdated = contentOffsetUpdated + self.contentOffsetWillCommit = contentOffsetWillCommit + } + + public static func ==(lhs: ScrollComponent, rhs: ScrollComponent) -> Bool { + if lhs.content != rhs.content { + return false + } + if lhs.contentInsets != rhs.contentInsets { + return false + } + + return true + } + + public final class View: UIScrollView, UIScrollViewDelegate { + private var component: ScrollComponent? + private let contentView: ComponentHostView<(ChildEnvironment, ScrollChildEnvironment)> + + override init(frame: CGRect) { + self.contentView = ComponentHostView() + + super.init(frame: frame) + + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.contentInsetAdjustmentBehavior = .never + } + self.delegate = self + self.showsVerticalScrollIndicator = false + self.showsHorizontalScrollIndicator = false + self.canCancelContentTouches = true + + self.addSubview(self.contentView) + } + + public override func touchesShouldCancel(in view: UIView) -> Bool { + return true + } + + private var ignoreDidScroll = false + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard let component = self.component, !self.ignoreDidScroll else { + return + } + let topOffset = scrollView.contentOffset.y + let bottomOffset = max(0.0, scrollView.contentSize.height - scrollView.contentOffset.y - scrollView.frame.height) + component.contentOffsetUpdated(topOffset, bottomOffset) + } + + public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + guard let component = self.component, !self.ignoreDidScroll else { + return + } + component.contentOffsetWillCommit(targetContentOffset) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: ScrollComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let contentSize = self.contentView.update( + transition: transition, + component: component.content, + environment: { + environment[ChildEnvironment.self] + ScrollChildEnvironment(insets: component.contentInsets) + }, + containerSize: CGSize(width: availableSize.width, height: .greatestFiniteMagnitude) + ) + transition.setFrame(view: self.contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil) + + if self.contentSize != contentSize { + self.ignoreDidScroll = true + self.contentSize = contentSize + self.ignoreDidScroll = false + } + if self.scrollIndicatorInsets != component.contentInsets { + self.scrollIndicatorInsets = component.contentInsets + } + + self.component = component + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/PromptUI/Sources/PromptController.swift b/submodules/PromptUI/Sources/PromptController.swift index ae86e0ba03..2b6dcbf2d8 100644 --- a/submodules/PromptUI/Sources/PromptController.swift +++ b/submodules/PromptUI/Sources/PromptController.swift @@ -409,7 +409,7 @@ public func promptController(sharedContext: SharedAccountContext, updatedPresent controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.inputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller] animated in diff --git a/submodules/ReactionSelectionNode/Sources/PremiumStarsNode.swift b/submodules/ReactionSelectionNode/Sources/PremiumStarsNode.swift new file mode 100644 index 0000000000..bdab92ec61 --- /dev/null +++ b/submodules/ReactionSelectionNode/Sources/PremiumStarsNode.swift @@ -0,0 +1,78 @@ +import Foundation +import AsyncDisplayKit +import Display +import SwiftSignalKit +import AppBundle + +private let starsCount = 9 +public final class PremiumStarsNode: ASDisplayNode { + private let starNodes: [ASImageNode] + private var timer: SwiftSignalKit.Timer? + + public override init() { + let image = UIImage(bundleImageName: "Premium/ReactionsStar") + var starNodes: [ASImageNode] = [] + for _ in 0 ..< starsCount { + let node = ASImageNode() + node.isLayerBacked = true + node.alpha = 0.0 + node.image = image + node.displaysAsynchronously = false + starNodes.append(node) + } + self.starNodes = starNodes + + super.init() + + for node in starNodes { + self.addSubnode(node) + } + + Queue.mainQueue().async { + self.setup(firstTime: true) + + self.timer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { [weak self] in + self?.setup() + }, queue: Queue.mainQueue()) + self.timer?.start() + } + } + + deinit { + self.timer?.invalidate() + } + + func setup(firstTime: Bool = false) { + let size: CGSize + if self.frame.width > 0.0 { + size = self.frame.size + } else { + size = CGSize(width: 32.0, height: 32.0) + } + let starSize = CGSize(width: 6.0, height: 8.0) + + for node in self.starNodes { + if node.layer.animation(forKey: "transform.scale") == nil && node.layer.animation(forKey: "opacity") == nil { + let x = CGFloat.random(in: 0 ..< size.width) + let y = CGFloat.random(in: 0 ..< size.width) + + let randomTargetScale = CGFloat.random(in: 0.8 ..< 1.0) + node.bounds = CGRect(origin: .zero, size: starSize) + node.position = CGPoint(x: x, y: y) + + node.alpha = 1.0 + + let duration = CGFloat.random(in: 0.4 ..< 0.65) + let delay = firstTime ? CGFloat.random(in: 0.0 ..< 0.25) : 0.0 + node.layer.animateScale(from: 0.001, to: randomTargetScale, duration: duration, delay: delay, removeOnCompletion: false, completion: { [weak self, weak node] _ in + let duration = CGFloat.random(in: 0.3 ..< 0.35) + node?.alpha = 0.0 + node?.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak self, weak node] _ in + node?.layer.removeAllAnimations() + self?.setup() + }) + }) + } + } + } +} diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index 7d3fa1470d..491273ad44 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -323,71 +323,6 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { } } -private let starsCount = 7 -private final class StarsNode: ASDisplayNode { - private let starNodes: [ASImageNode] - private var timer: SwiftSignalKit.Timer? - - override init() { - let image = UIImage(bundleImageName: "Premium/ReactionsStar") - var starNodes: [ASImageNode] = [] - for _ in 0 ..< starsCount { - let node = ASImageNode() - node.alpha = 0.0 - node.image = image - node.displaysAsynchronously = false - starNodes.append(node) - } - self.starNodes = starNodes - - super.init() - - for node in starNodes { - self.addSubnode(node) - } - - self.setup(firstTime: true) - - self.timer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { [weak self] in - self?.setup() - }, queue: Queue.mainQueue()) - self.timer?.start() - } - - deinit { - self.timer?.invalidate() - } - - func setup(firstTime: Bool = false) { - let size = CGSize(width: 32.0, height: 32.0) - let starSize = CGSize(width: 6.0, height: 8.0) - - for node in self.starNodes { - if node.layer.animation(forKey: "transform.scale") == nil && node.layer.animation(forKey: "opacity") == nil { - let x = CGFloat.random(in: 0 ..< size.width) - let y = CGFloat.random(in: 0 ..< size.width) - - let randomTargetScale = CGFloat.random(in: 0.8 ..< 1.0) - node.bounds = CGRect(origin: .zero, size: starSize) - node.position = CGPoint(x: x, y: y) - - node.alpha = 1.0 - - let duration = CGFloat.random(in: 0.4 ..< 0.65) - let delay = firstTime ? CGFloat.random(in: 0.0 ..< 0.25) : 0.0 - node.layer.animateScale(from: 0.001, to: randomTargetScale, duration: duration, delay: delay, removeOnCompletion: false, completion: { [weak self, weak node] _ in - let duration = CGFloat.random(in: 0.3 ..< 0.35) - node?.alpha = 0.0 - node?.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak self, weak node] _ in - node?.layer.removeAllAnimations() - self?.setup() - }) - }) - } - } - } -} - final class PremiumReactionsNode: ASDisplayNode, ReactionItemNode { var isExtracted: Bool = false @@ -395,7 +330,7 @@ final class PremiumReactionsNode: ASDisplayNode, ReactionItemNode { private let backgroundMaskNode: ASImageNode private let backgroundOverlayNode: ASImageNode private let imageNode: ASImageNode - private var starsNode: StarsNode? + private var starsNode: PremiumStarsNode? private let maskContainerNode: ASDisplayNode private let maskImageNode: ASImageNode @@ -459,7 +394,7 @@ final class PremiumReactionsNode: ASDisplayNode, ReactionItemNode { self.view.insertSubview(backgroundView, at: 0) self.backgroundView = backgroundView - let starsNode = StarsNode() + let starsNode = PremiumStarsNode() starsNode.frame = CGRect(origin: .zero, size: CGSize(width: 32.0, height: 32.0)) self.backgroundView?.contentView.addSubview(starsNode.view) self.starsNode = starsNode diff --git a/submodules/SSignalKit/SwiftSignalKit/Source/QueueLocalObject.swift b/submodules/SSignalKit/SwiftSignalKit/Source/QueueLocalObject.swift index 9265f752ba..95d5f65081 100644 --- a/submodules/SSignalKit/SwiftSignalKit/Source/QueueLocalObject.swift +++ b/submodules/SSignalKit/SwiftSignalKit/Source/QueueLocalObject.swift @@ -20,6 +20,11 @@ public final class QueueLocalObject { } } + public func unsafeGet() -> T? { + assert(self.queue.isCurrent()) + return self.valueRef?.takeUnretainedValue() + } + public func with(_ f: @escaping (T) -> Void) { self.queue.async { if let valueRef = self.valueRef { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 518a82eaee..941ee762f7 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -167,22 +167,22 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) - let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) - let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let width: CGFloat diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index ce7a7166b5..7f0f102541 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -478,7 +478,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_cancel") dismissImpl?() - })])) + })], actionLayout: .vertical)) } } diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift index 24d4cb6225..ee5d3026bb 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -363,7 +363,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo })) }) ]) - alertController.dismissed = { + alertController.dismissed = { _ in addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_cancel") } presentControllerImpl?(alertController, nil) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index 8bce683aec..4760003e13 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -149,7 +149,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false) + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false) var node: ListViewItemNode? if let current = currentNode { diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 7a070c170a..95bf79323e 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -14,6 +14,8 @@ import TelegramNotices import LocalAuth import AppBundle import PasswordSetupUI +import UndoUI +import PremiumUI private final class PrivacyAndSecurityControllerArguments { let account: Account @@ -24,6 +26,7 @@ private final class PrivacyAndSecurityControllerArguments { let openProfilePhotoPrivacy: () -> Void let openForwardPrivacy: () -> Void let openPhoneNumberPrivacy: () -> Void + let openVoiceMessagePrivacy: () -> Void let openPasscode: () -> Void let openTwoStepVerification: (TwoStepVerificationAccessConfiguration?) -> Void let openActiveSessions: () -> Void @@ -31,7 +34,7 @@ private final class PrivacyAndSecurityControllerArguments { let setupAccountAutoremove: () -> Void let openDataSettings: () -> Void - init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void) { + init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void) { self.account = account self.openBlockedUsers = openBlockedUsers self.openLastSeenPrivacy = openLastSeenPrivacy @@ -40,6 +43,7 @@ private final class PrivacyAndSecurityControllerArguments { self.openProfilePhotoPrivacy = openProfilePhotoPrivacy self.openForwardPrivacy = openForwardPrivacy self.openPhoneNumberPrivacy = openPhoneNumberPrivacy + self.openVoiceMessagePrivacy = openVoiceMessagePrivacy self.openPasscode = openPasscode self.openTwoStepVerification = openTwoStepVerification self.openActiveSessions = openActiveSessions @@ -79,6 +83,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case voiceCallPrivacy(PresentationTheme, String, String) case forwardPrivacy(PresentationTheme, String, String) case groupPrivacy(PresentationTheme, String, String) + case voiceMessagePrivacy(PresentationTheme, String, String, Bool) case selectivePrivacyInfo(PresentationTheme, String) case passcode(PresentationTheme, String, Bool, String) case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?) @@ -96,7 +101,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { switch self { case .blockedPeers, .activeSessions, .passcode, .twoStepVerification: return PrivacyAndSecuritySection.general.rawValue - case .privacyHeader, .phoneNumberPrivacy, .lastSeenPrivacy, .profilePhotoPrivacy, .forwardPrivacy, .groupPrivacy, .selectivePrivacyInfo, .voiceCallPrivacy: + case .privacyHeader, .phoneNumberPrivacy, .lastSeenPrivacy, .profilePhotoPrivacy, .forwardPrivacy, .groupPrivacy, .voiceCallPrivacy, .voiceMessagePrivacy, .selectivePrivacyInfo: return PrivacyAndSecuritySection.privacy.rawValue case .autoArchiveHeader, .autoArchive, .autoArchiveInfo: return PrivacyAndSecuritySection.autoArchive.rawValue @@ -127,28 +132,30 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return 8 case .voiceCallPrivacy: return 9 - case .forwardPrivacy: + case .voiceMessagePrivacy: return 10 - case .groupPrivacy: + case .forwardPrivacy: return 11 - case .selectivePrivacyInfo: + case .groupPrivacy: return 12 - case .autoArchiveHeader: + case .selectivePrivacyInfo: return 13 - case .autoArchive: + case .autoArchiveHeader: return 14 - case .autoArchiveInfo: + case .autoArchive: return 15 - case .accountHeader: + case .autoArchiveInfo: return 16 - case .accountTimeout: + case .accountHeader: return 17 - case .accountInfo: + case .accountTimeout: return 18 - case .dataSettings: + case .accountInfo: return 19 - case .dataSettingsInfo: + case .dataSettings: return 20 + case .dataSettingsInfo: + return 21 } } @@ -196,14 +203,20 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { } else { return false } - case let .selectivePrivacyInfo(lhsTheme, lhsText): - if case let .selectivePrivacyInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + case let .voiceCallPrivacy(lhsTheme, lhsText, lhsValue): + if case let .voiceCallPrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { return true } else { return false } - case let .voiceCallPrivacy(lhsTheme, lhsText, lhsValue): - if case let .voiceCallPrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue, lhsLocked): + if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue, rhsLocked) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsLocked == rhsLocked { + return true + } else { + return false + } + case let .selectivePrivacyInfo(lhsTheme, lhsText): + if case let .selectivePrivacyInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true } else { return false @@ -287,7 +300,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { case let .privacyHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .blockedPeers(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Settings/Menu/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: { + return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Chat/Stickers/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: { arguments.openBlockedUsers() }) case let .phoneNumberPrivacy(_, text, value): @@ -310,6 +323,10 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { arguments.openGroupsPrivacy() }) + case let .voiceMessagePrivacy(_, text, value, locked): + return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: locked ? .textWithIcon(UIImage(bundleImageName: "Notification/SecretLock")!.precomposed()) : .text, sectionId: self.section, style: .blocks, action: { + arguments.openVoiceMessagePrivacy() + }) case let .selectivePrivacyInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .voiceCallPrivacy(_, text, value): @@ -394,7 +411,7 @@ private func stringForSelectiveSettings(strings: PresentationStrings, settings: } } -private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool) -> [PrivacyAndSecurityEntry] { +private func privacyAndSecurityControllerEntries(presentationData: PresentationData, state: PrivacyAndSecurityControllerState, privacySettings: AccountPrivacySettings?, accessChallengeData: PostboxAccessChallengeData, blockedPeerCount: Int?, activeWebsitesCount: Int, hasTwoStepAuth: Bool?, twoStepAuthData: TwoStepVerificationAccessConfiguration?, canAutoarchive: Bool, isPremium: Bool) -> [PrivacyAndSecurityEntry] { var entries: [PrivacyAndSecurityEntry] = [] entries.append(.blockedPeers(presentationData.theme, presentationData.strings.Settings_BlockedUsers, blockedPeerCount == nil ? "" : (blockedPeerCount == 0 ? presentationData.strings.PrivacySettings_BlockedPeersEmpty : "\(blockedPeerCount!)"))) @@ -432,6 +449,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.presence))) entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.profilePhoto))) entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls))) + entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages), !isPremium)) entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.forwards))) entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.groupInvitations))) @@ -440,6 +458,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.lastSeenPrivacy(presentationData.theme, presentationData.strings.PrivacySettings_LastSeen, presentationData.strings.Channel_NotificationLoading)) entries.append(.profilePhotoPrivacy(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto, presentationData.strings.Channel_NotificationLoading)) entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading)) + entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading, !isPremium)) entries.append(.forwardPrivacy(presentationData.theme, presentationData.strings.Privacy_Forwards, presentationData.strings.Channel_NotificationLoading)) entries.append(.groupPrivacy(presentationData.theme, presentationData.strings.Privacy_GroupsAndChannels, presentationData.strings.Channel_NotificationLoading)) entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp)) @@ -582,7 +601,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: updated, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: updated, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -605,7 +624,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: updated, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: updated, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -642,7 +661,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: updated, voiceCallsP2P: updatedCallsPrivacy, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: updated, voiceCallsP2P: updatedCallsPrivacy, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -665,7 +684,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: updated, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: updated, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -688,7 +707,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: updated, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: updated, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -711,7 +730,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: updated, phoneDiscoveryEnabled: updatedDiscoveryEnabled ?? value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: updated, phoneDiscoveryEnabled: updatedDiscoveryEnabled ?? value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -720,6 +739,49 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting }), true) } })) + }, openVoiceMessagePrivacy: { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let signal = combineLatest( + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)), + privacySettingsPromise.get() + ) + |> take(1) + |> deliverOnMainQueue + currentInfoDisposable.set(signal.start(next: { [weak currentInfoDisposable] peer, info in + let isPremium = peer?.isPremium ?? false + + if isPremium { + if let info = info { + pushControllerImpl?(selectivePrivacySettingsController(context: context, kind: .voiceMessages, current: info.voiceMessages, updated: { updated, _, _ in + if let currentInfoDisposable = currentInfoDisposable { + let applySetting: Signal = privacySettingsPromise.get() + |> filter { $0 != nil } + |> take(1) + |> deliverOnMainQueue + |> mapToSignal { value -> Signal in + if let value = value { + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: updated, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: value.accountRemovalTimeout))) + } + return .complete() + } + currentInfoDisposable.set(applySetting.start()) + } + }), true) + } + } else { + let hapticFeedback = HapticFeedback() + hapticFeedback.impact() + + presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Privacy_VoiceMessages_Tooltip), elevatedLayout: false, animateInAsReplacement: false, action: { action in + if action == .info { + let controller = PremiumIntroScreen(context: context, source: .settings) + pushControllerImpl?(controller, true) + return true + } + return false + })) + } + })) }, openPasscode: { let _ = passcodeOptionsAccessController(context: context, pushController: { controller in replaceTopControllerImpl?(controller) @@ -767,7 +829,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: archiveValue, accountRemovalTimeout: value.accountRemovalTimeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: archiveValue, accountRemovalTimeout: value.accountRemovalTimeout))) } return .complete() } @@ -806,7 +868,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting |> deliverOnMainQueue |> mapToSignal { value -> Signal in if let value = value { - privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: timeout))) + privacySettingsPromise.set(.single(AccountPrivacySettings(presence: value.presence, groupInvitations: value.groupInvitations, voiceCalls: value.voiceCalls, voiceCallsP2P: value.voiceCallsP2P, profilePhoto: value.profilePhoto, forwards: value.forwards, phoneNumber: value.phoneNumber, phoneDiscoveryEnabled: value.phoneDiscoveryEnabled, voiceMessages: value.voiceMessages, automaticallyArchiveAndMuteNonContacts: value.automaticallyArchiveAndMuteNonContacts, accountRemovalTimeout: timeout))) } return .complete() } @@ -882,9 +944,10 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()) + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()), + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) ) - |> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration, accountPeer -> (ItemListControllerState, (ItemListNodeState, Any)) in var canAutoarchive = false if let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool { canAutoarchive = hasAutoarchive @@ -897,7 +960,9 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PrivacySettings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) + let isPremium = accountPeer?.isPremium ?? false + + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremium: isPremium), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false) return (controllerState, (listState, arguments)) } @@ -913,7 +978,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting (controller?.navigationController as? NavigationController)?.replaceTopController(c, animated: true) } presentControllerImpl = { [weak controller] c in - controller?.present(c, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + controller?.present(c, in: .window(.root), with: nil) } getNavigationControllerImpl = { [weak controller] in return (controller?.navigationController as? NavigationController) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift index 93845fa5fe..ca363fb63f 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/SelectivePrivacySettingsController.swift @@ -18,6 +18,7 @@ enum SelectivePrivacySettingsKind { case profilePhoto case forwards case phoneNumber + case voiceMessages } private enum SelectivePrivacySettingType { @@ -580,6 +581,11 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present } disableForText = presentationData.strings.PrivacyLastSeenSettings_NeverShareWith enableForText = presentationData.strings.PrivacyLastSeenSettings_AlwaysShareWith + case .voiceMessages: + settingTitle = presentationData.strings.Privacy_VoiceMessages_WhoCanSend + settingInfoText = presentationData.strings.Privacy_VoiceMessages_CustomHelp + disableForText = presentationData.strings.Privacy_GroupsAndChannels_NeverAllow + enableForText = presentationData.strings.Privacy_GroupsAndChannels_AlwaysAllow } if case .forwards = kind { @@ -605,7 +611,7 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody)) entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts)) switch kind { - case .presence, .voiceCalls, .forwards, .phoneNumber: + case .presence, .voiceCalls, .forwards, .phoneNumber, .voiceMessages: entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody)) case .groupInvitations, .profilePhoto: break @@ -731,6 +737,8 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective title = strings.Privacy_Forwards_AlwaysAllow_Title case .phoneNumber: title = strings.PrivacyLastSeenSettings_AlwaysShareWith_Title + case .voiceMessages: + title = strings.Privacy_VoiceMessages_AlwaysAllow_Title } } else { switch kind { @@ -746,6 +754,8 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective title = strings.Privacy_Forwards_NeverAllow_Title case .phoneNumber: title = strings.PrivacyLastSeenSettings_NeverShareWith_Title + case .voiceMessages: + title = strings.Privacy_VoiceMessages_NeverAllow_Title } } var peerIds: [PeerId: SelectivePrivacyPeer] = [:] @@ -981,6 +991,8 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective title = presentationData.strings.Privacy_Forwards case .phoneNumber: title = presentationData.strings.Privacy_PhoneNumber + case .voiceMessages: + title = presentationData.strings.Privacy_VoiceMessages } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false) let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: selectivePrivacySettingsControllerEntries(presentationData: presentationData, kind: kind, state: state, peerName: peerName ?? "", phoneNumber: phoneNumber), style: .blocks, animateChanges: false) @@ -1059,6 +1071,8 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective type = .forwards case .phoneNumber: type = .phoneNumber + case .voiceMessages: + type = .voiceMessages } let updateSettingsSignal = context.engine.privacy.updateSelectiveAccountPrivacySettings(type: type, settings: settings) diff --git a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift index e8251dacea..8a21c853c2 100644 --- a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift @@ -227,7 +227,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { attributes.append(ReactionsMessageAttribute(canViewList: false, reactions: [MessageReaction(value: reaction, count: 1, isSelected: true)], recentPeers: [])) } - let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, isCentered: true) + let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, isCentered: true) var node: ListViewItemNode? if let current = currentNode { diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift index 3a6ee7ba28..8126680001 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift @@ -456,6 +456,8 @@ private func privacySearchableItems(context: AccountContext, privacySettings: Ac current = info.forwards case .phoneNumber: current = info.phoneNumber + case .voiceMessages: + current = info.voiceMessages } present(.push, selectivePrivacySettingsController(context: context, kind: kind, current: current, callSettings: callSettings != nil ? (info.voiceCallsP2P, callSettings!.0) : nil, voipConfiguration: callSettings?.1, callIntegrationAvailable: CallKitIntegration.isAvailable, updated: { updated, updatedCallSettings, _ in diff --git a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift index 5435c455ce..9ca55c66fd 100644 --- a/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/ArchivedStickerPacksController.swift @@ -17,6 +17,7 @@ import UndoUI public enum ArchivedStickerPacksControllerMode { case stickers case masks + case emoji } private final class ArchivedStickerPacksControllerArguments { @@ -206,7 +207,16 @@ private func archivedStickerPacksControllerEntries(presentationData: Presentatio var index: Int32 = 0 for item in packs { if !installedIds.contains(item.info.id) { - entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false, selectable: true))) + let countTitle: String + if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count) + } else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count) + } + + entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, item.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, !state.removingPackIds.contains(item.info.id), ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == item.info.id, reorderable: false, selectable: true))) index += 1 } } @@ -237,6 +247,8 @@ public func archivedStickerPacksController(context: AccountContext, mode: Archiv switch mode { case .stickers: namespace = .stickers + case .emoji: + namespace = .emoji case .masks: namespace = .masks } diff --git a/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift index aac83cf4fb..872d61209d 100644 --- a/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/FeaturedStickerPacksController.swift @@ -138,7 +138,17 @@ private func featuredStickerPacksControllerEntries(presentationData: Presentatio if let value = unreadPacks[item.info.id] { unread = value } - entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, presentationData.strings.StickerPack_StickerCount(item.info.count), stickerSettings.loopAnimatedStickers, installedPacks.contains(item.info.id))) + + let countTitle: String + if item.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(item.info.count) + } else if item.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(item.info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(item.info.count) + } + + entries.append(.pack(index, presentationData.theme, presentationData.strings, item.info, unread, item.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, installedPacks.contains(item.info.id))) index += 1 } } diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index d9db23d840..73d10a8f52 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -26,6 +26,7 @@ private final class InstalledStickerPacksControllerArguments { let removePack: (ArchivedStickerPackItem) -> Void let openStickersBot: () -> Void let openMasks: () -> Void + let openEmoji: () -> Void let openQuickReaction: () -> Void let openFeatured: () -> Void let openArchived: ([ArchivedStickerPackItem]?) -> Void @@ -35,13 +36,14 @@ private final class InstalledStickerPacksControllerArguments { let expandTrendingPacks: () -> Void let addPack: (StickerPackCollectionInfo) -> Void - init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openQuickReaction: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleAnimatedStickers: @escaping (Bool) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void, expandTrendingPacks: @escaping () -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void) { + init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ArchivedStickerPackItem) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openEmoji: @escaping () -> Void, openQuickReaction: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void, toggleAnimatedStickers: @escaping (Bool) -> Void, togglePackSelected: @escaping (ItemCollectionId) -> Void, expandTrendingPacks: @escaping () -> Void, addPack: @escaping (StickerPackCollectionInfo) -> Void) { self.account = account self.openStickerPack = openStickerPack self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions self.removePack = removePack self.openStickersBot = openStickersBot self.openMasks = openMasks + self.openEmoji = openEmoji self.openQuickReaction = openQuickReaction self.openFeatured = openFeatured self.openArchived = openArchived @@ -83,6 +85,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { case trending(PresentationTheme, String, Int32) case archived(PresentationTheme, String, Int32, [ArchivedStickerPackItem]?) case masks(PresentationTheme, String) + case emoji(PresentationTheme, String) case quickReaction(String, UIImage?) case animatedStickers(PresentationTheme, String, Bool) case animatedStickersInfo(PresentationTheme, String) @@ -95,7 +98,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { var section: ItemListSectionId { switch self { - case .suggestOptions, .trending, .masks, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo: + case .suggestOptions, .trending, .masks, .emoji, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo: return InstalledStickerPacksSection.service.rawValue case .trendingPacksTitle, .trendingPack, .trendingExpand: return InstalledStickerPacksSection.trending.rawValue @@ -114,24 +117,26 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { return .index(2) case .masks: return .index(3) - case .quickReaction: + case .emoji: return .index(4) - case .animatedStickers: + case .quickReaction: return .index(5) - case .animatedStickersInfo: + case .animatedStickers: return .index(6) - case .trendingPacksTitle: + case .animatedStickersInfo: return .index(7) + case .trendingPacksTitle: + return .index(8) case let .trendingPack(_, _, _, info, _, _, _, _, _): return .trendingPack(info.id) case .trendingExpand: - return .index(8) - case .packsTitle: return .index(9) + case .packsTitle: + return .index(10) case let .pack(_, _, _, info, _, _, _, _, _, _): return .pack(info.id) case .packsInfo: - return .index(10) + return .index(11) } } @@ -155,6 +160,12 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { } else { return false } + case let .emoji(lhsTheme, lhsCount): + if case let .emoji(rhsTheme, rhsCount) = rhs, lhsTheme === rhsTheme, lhsCount == rhsCount { + return true + } else { + return false + } case let .quickReaction(lhsText, lhsImage): if case let .quickReaction(rhsText, rhsImage) = rhs, lhsText == rhsText, lhsImage === rhsImage { return true @@ -305,30 +316,37 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { default: return true } + case .emoji: + switch rhs { + case .suggestOptions, .trending, .archived, .masks, .emoji: + return false + default: + return true + } case .quickReaction: switch rhs { - case .suggestOptions, .trending, .archived, .masks, .quickReaction: + case .suggestOptions, .trending, .archived, .masks, .emoji, .quickReaction: return false default: return true } case .animatedStickers: switch rhs { - case .suggestOptions, .trending, .archived, .masks, .quickReaction, .animatedStickers: + case .suggestOptions, .trending, .archived, .masks, .emoji, .quickReaction, .animatedStickers: return false default: return true } case .animatedStickersInfo: switch rhs { - case .suggestOptions, .trending, .archived, .masks, .quickReaction, .animatedStickers, .animatedStickersInfo: + case .suggestOptions, .trending, .archived, .masks, .emoji, .quickReaction, .animatedStickers, .animatedStickersInfo: return false default: return true } case .trendingPacksTitle: switch rhs { - case .suggestOptions, .trending, .masks, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle: + case .suggestOptions, .trending, .masks, .emoji, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle: return false default: return true @@ -344,14 +362,14 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { } case .trendingExpand: switch rhs { - case .suggestOptions, .trending, .masks, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand: + case .suggestOptions, .trending, .masks, .emoji, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand: return false default: return true } case .packsTitle: switch rhs { - case .suggestOptions, .trending, .masks, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand, .packsTitle: + case .suggestOptions, .trending, .masks, .emoji, .quickReaction, .archived, .animatedStickers, .animatedStickersInfo, .trendingPacksTitle, .trendingPack, .trendingExpand, .packsTitle: return false default: return true @@ -390,6 +408,10 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { arguments.openMasks() }) + case let .emoji(_, text): + return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: { + arguments.openEmoji() + }) case let .quickReaction(title, image): let labelStyle: ItemListDisclosureLabelStyle if let image = image { @@ -505,6 +527,8 @@ private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> It return Namespaces.ItemCollection.CloudStickerPacks case .masks: return Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + return Namespaces.ItemCollection.CloudEmojiPacks } } @@ -544,6 +568,8 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title)) + entries.append(.emoji(presentationData.theme, presentationData.strings.StickersList_EmojiItem)) + entries.append(.quickReaction(presentationData.strings.Settings_QuickReactionSetup_NavigationTitle, quickReactionImage)) entries.append(.animatedStickers(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickers, stickerSettings.loopAnimatedStickers)) @@ -562,7 +588,16 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } for featuredPack in featuredPacks { - entries.append(.trendingPack(index, presentationData.theme, presentationData.strings, featuredPack.info, featuredPack.topItems.first, presentationData.strings.StickerPack_StickerCount(featuredPack.info.count), stickerSettings.loopAnimatedStickers, featuredPack.unread, installedPacks.contains(featuredPack.info.id))) + let countTitle: String + if featuredPack.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(featuredPack.info.count) + } else if featuredPack.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(featuredPack.info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(featuredPack.info.count) + } + + entries.append(.trendingPack(index, presentationData.theme, presentationData.strings, featuredPack.info, featuredPack.topItems.first, countTitle, stickerSettings.loopAnimatedStickers, featuredPack.unread, installedPacks.contains(featuredPack.info.id))) index += 1 } @@ -576,6 +611,10 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati if let archived = archived, !archived.isEmpty { entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedMasks, Int32(archived.count), archived)) } + case .emoji: + if let archived = archived, !archived.isEmpty { + entries.append(.archived(presentationData.theme, presentationData.strings.StickersList_ArchivedEmojiItem, Int32(archived.count), archived)) + } } if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView { @@ -605,7 +644,16 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati var index: Int32 = 0 for entry in sortedPacks { if let info = entry.info as? StickerPackCollectionInfo { - entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count), stickerSettings.loopAnimatedStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id))) + let countTitle: String + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + countTitle = presentationData.strings.StickerPack_EmojiCount(info.count == 0 ? entry.count : info.count) + } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + countTitle = presentationData.strings.StickerPack_MaskCount(info.count == 0 ? entry.count : info.count) + } else { + countTitle = presentationData.strings.StickerPack_StickerCount(info.count == 0 ? entry.count : info.count) + } + + entries.append(.pack(index, presentationData.theme, presentationData.strings, info, entry.firstItem as? StickerPackItem, countTitle, stickerSettings.loopAnimatedStickers, true, ItemListStickerPackItemEditing(editable: true, editing: state.editing, revealed: state.packIdWithRevealedOptions == entry.id, reorderable: true, selectable: true), state.selectedPackIds?.contains(info.id))) index += 1 } } @@ -618,6 +666,8 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati markdownString = presentationData.strings.StickerPacksSettings_ManagingHelp case .masks: markdownString = presentationData.strings.MaskStickerSettings_Info + case .emoji: + markdownString = presentationData.strings.EmojiStickerSettings_Info } let entities = generateTextEntities(markdownString, enabledTypes: [.mention]) if let entity = entities.first { @@ -633,6 +683,7 @@ public enum InstalledStickerPacksControllerMode { case general case modal case masks + case emoji } public func installedStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, archivedPacks: [ArchivedStickerPackItem]? = nil, updatedPacks: @escaping ([ArchivedStickerPackItem]?) -> Void = { _ in }, focusOnItemTag: InstalledStickerPacksEntryTag? = nil) -> ViewController { @@ -691,17 +742,40 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } } - navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).string, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in + let removedTitle: String + let removedText: String + if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + removedTitle = action == .archive ? presentationData.strings.EmojiPackActionInfo_ArchivedTitle : presentationData.strings.EmojiPackActionInfo_RemovedTitle + removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(archivedItem.info.title).string + } else if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + removedTitle = action == .archive ? presentationData.strings.MaskPackActionInfo_ArchivedTitle : presentationData.strings.MaskPackActionInfo_RemovedTitle + removedText = presentationData.strings.MaskPackActionInfo_RemovedText(archivedItem.info.title).string + } else { + removedTitle = action == .archive ? presentationData.strings.StickerPackActionInfo_ArchivedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle + removedText = presentationData.strings.StickerPackActionInfo_RemovedText(archivedItem.info.title).string + } + + navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: archivedItem.info, topItem: archivedItem.topItems.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: archivedItem.info, items: items, positionInList: positionInList).start() + let _ = context.engine.stickers.addStickerPackInteractively(info: archivedItem.info, items: items.compactMap({ $0 as? StickerPackItem }), positionInList: positionInList).start() } return true })) }) } + + let title: String + if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + title = presentationData.strings.StickerSettings_EmojiContextInfo + } else if archivedItem.info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + title = presentationData.strings.StickerSettings_MaskContextInfo + } else { + title = presentationData.strings.StickerSettings_ContextInfo + } + controller.setItemGroups([ ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: presentationData.strings.StickerSettings_ContextInfo), + ActionSheetTextItem(title: title), ActionSheetButtonItem(title: presentationData.strings.StickerSettings_ContextHide, color: .accent, action: { dismissAction() @@ -731,6 +805,8 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta })) }, openMasks: { pushControllerImpl?(installedStickerPacksController(context: context, mode: .masks, archivedPacks: archivedPacks, updatedPacks: { _ in})) + }, openEmoji: { + pushControllerImpl?(installedStickerPacksController(context: context, mode: .emoji, archivedPacks: archivedPacks, updatedPacks: { _ in})) }, openQuickReaction: { pushControllerImpl?(quickReactionSetupController( context: context @@ -742,6 +818,8 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta switch mode { case .masks: archivedMode = .masks + case .emoji: + archivedMode = .emoji default: archivedMode = .stickers } @@ -876,6 +954,10 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta featured.set(.single([])) archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .masks) |> map(Optional.init))) quickReactionImage = .single(nil) + case .emoji: + featured.set(.single([])) + archivedPromise.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks(namespace: .emoji) |> map(Optional.init))) + quickReactionImage = .single(nil) } var previousPackCount: Int? @@ -1027,6 +1109,8 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta title = presentationData.strings.StickerPacksSettings_Title case .masks: title = presentationData.strings.MaskStickerSettings_Title + case .emoji: + title = presentationData.strings.EmojiPacksSettings_Title } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) @@ -1183,7 +1267,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta packs.insert(packReference, at: 0) } if let mainStickerPack = mainStickerPack { - presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: packs, parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { info, items, action in + presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { actions in let presentationData = context.sharedContext.currentPresentationData.with { $0 } var animateInAsReplacement = false if let navigationController = navigationControllerImpl?() { @@ -1194,18 +1278,33 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta } } } - switch action { - case .add: - navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - })) - case let .remove(positionInList): - navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + if let (info, items, action) = actions.first { + switch action { + case .add: + navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + })) + case let .remove(positionInList): + let removedTitle: String + let removedText: String + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + removedTitle = presentationData.strings.EmojiPackActionInfo_RemovedTitle + removedText = presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string + } else if info.id.namespace == Namespaces.ItemCollection.CloudMaskPacks { + removedTitle = presentationData.strings.MaskPackActionInfo_RemovedTitle + removedText = presentationData.strings.MaskPackActionInfo_RemovedText(info.title).string + } else { + removedTitle = presentationData.strings.StickerPackActionInfo_RemovedTitle + removedText = presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string } - return true - })) + + navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: removedTitle, text: removedText, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } } }), nil) } diff --git a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift index 5e1058e9de..cb991de4aa 100644 --- a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift +++ b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift @@ -60,7 +60,7 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { let fontSize = floor(presentationData.listsFontSize.baseDisplaySize * 15.0 / 17.0) - self.contentTextNode.attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: presentationData.theme.list.itemPrimaryTextColor, linkColor: presentationData.theme.list.itemAccentColor, baseFont: Font.regular(fontSize), linkFont: Font.regular(fontSize), boldFont: Font.semibold(fontSize), italicFont: Font.italic(fontSize), boldItalicFont: Font.semiboldItalic(fontSize), fixedFont: Font.monospace(fontSize), blockQuoteFont: Font.regular(fontSize)) + self.contentTextNode.attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: presentationData.theme.list.itemPrimaryTextColor, linkColor: presentationData.theme.list.itemAccentColor, baseFont: Font.regular(fontSize), linkFont: Font.regular(fontSize), boldFont: Font.semibold(fontSize), italicFont: Font.italic(fontSize), boldItalicFont: Font.semiboldItalic(fontSize), fixedFont: Font.monospace(fontSize), blockQuoteFont: Font.regular(fontSize), message: nil) self.toolbarNode = ASDisplayNode() self.toolbarSeparatorNode = ASDisplayNode() diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 0fae46c287..0e7ceca482 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -210,7 +210,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in gesture?.cancel() @@ -256,7 +256,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView media: [], peers: [:], associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) ], peer: EngineRenderedPeer(peer: peer), @@ -411,22 +412,22 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) - let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA=" let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) - let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) - let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false)) let width: CGFloat diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index f02b48e1eb..a620c20fa7 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -1259,7 +1259,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift index 0b894e70a8..9d68f1e533 100644 --- a/submodules/SettingsUI/Sources/Themes/EditThemeController.swift +++ b/submodules/SettingsUI/Sources/Themes/EditThemeController.swift @@ -537,7 +537,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll |> take(1)).start(next: { previewTheme, settings in let saveThemeTemplateFile: (String, LocalFileMediaResource, @escaping () -> Void) -> Void = { title, resource, completion in let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: resource.fileId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(title).tgios-theme")]) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start() diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index c81f297f4f..309f10eed5 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -830,7 +830,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in gesture?.cancel() @@ -876,7 +876,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate media: [], peers: [:], associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) ], peer: EngineRenderedPeer(peer: peer), @@ -1002,20 +1003,20 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate var sampleMessages: [Message] = [] - let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message1) - let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message2) - let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message3) - let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) messages[message5.id] = message5 sampleMessages.append(message5) @@ -1023,13 +1024,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) - let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message7) - let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message8) items = sampleMessages.reversed().map { message in diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 1345575f73..b543c852c4 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -354,7 +354,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] - let interaction = ChatListNodeInteraction(activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in + let interaction = ChatListNodeInteraction(context: self.context, activateSearch: {}, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in }, messageSelected: { _, _, _ in}, groupSelected: { _ in }, addContact: { _ in }, setPeerIdWithRevealedOptions: { _, _ in }, setItemPinned: { _, _ in }, setPeerMuted: { _, _ in }, deletePeer: { _, _ in }, updatePeerGrouping: { _, _ in }, togglePeerMarkedUnread: { _, _ in}, toggleArchivedFolderHiddenByDefault: {}, hidePsa: { _ in }, activateChatPreview: { _, _, gesture in gesture?.cancel() @@ -399,7 +399,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { media: [], peers: [:], associatedMessages: [:], - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) ], peer: EngineRenderedPeer(peer: peer), @@ -563,20 +564,20 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { var sampleMessages: [Message] = [] - let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message1) - let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message2) - let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message3) - let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) messages[message4.id] = message4 sampleMessages.append(message4) - let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) messages[message5.id] = message5 sampleMessages.append(message5) @@ -584,13 +585,13 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)] let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes) - let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message6) - let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message7) - let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) sampleMessages.append(message8) items = sampleMessages.reversed().map { message in diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index b3e60eb831..775a8121bb 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -156,10 +156,10 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) if let (author, text) = messageItem.reply { peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) - messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index c5f815fe6e..137d752d52 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -1405,7 +1405,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index 3fa36563e1..2ec60acc6d 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -1102,10 +1102,10 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let theme = self.presentationData.theme.withUpdated(preview: true) - let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false)) - let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: []) + let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:]) items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false)) let params = ListViewItemLayoutParams(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, availableHeight: layout.size.height) diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index addc248941..35302bd629 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -583,9 +583,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: url + "\n\n" + text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } else { - messages.append(.message(text: url, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) @@ -594,9 +594,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } - messages.append(.message(text: string, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -604,19 +604,19 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber]) attributedText.append(NSAttributedString(string: "\n\n\(url)")) let entities = generateChatInputTextEntities(attributedText) - messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } case let .image(representations): for peerId in peerIds { var messages: [EnqueueMessage] = [] - messages.append(.message(text: text, attributes: [], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -629,9 +629,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty && !sendTextAsCaption { - messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } - messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -639,9 +639,9 @@ public final class ShareController: ViewController { for peerId in peerIds { var messages: [EnqueueMessage] = [] if !text.isEmpty { - messages.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } - messages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) messages = transformMessages(messages, showNames: showNames, silently: silently) shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages)) } @@ -649,7 +649,7 @@ public final class ShareController: ViewController { for peerId in peerIds { var messagesToEnqueue: [EnqueueMessage] = [] if !text.isEmpty { - messagesToEnqueue.append(.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } for message in messages { messagesToEnqueue.append(.forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil)) diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index 0130b9cb35..e014df4d9b 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -650,21 +650,23 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate let doneImpl: (Bool) -> Void = { [weak self] shouldDelay in let minDelay: Double = shouldDelay ? 0.9 : 0.6 let delay: Double + let hapticDelay: Double + if let strongSelf = self, let contentNode = strongSelf.contentNode as? ShareProlongedLoadingContainerNode { delay = contentNode.completionDuration - - if shouldDelay { - Queue.mainQueue().after(delay - 1.5, { - if strongSelf.hapticFeedback == nil { - strongSelf.hapticFeedback = HapticFeedback() - } - strongSelf.hapticFeedback?.success() - }) - } + hapticDelay = shouldDelay ? delay - 1.5 : delay } else { delay = max(minDelay, (timestamp + minDelay) - CACurrentMediaTime()) + hapticDelay = delay } - + + Queue.mainQueue().after(hapticDelay, { + if self?.hapticFeedback == nil { + self?.hapticFeedback = HapticFeedback() + } + self?.hapticFeedback?.success() + }) + Queue.mainQueue().after(delay, { self?.animateOut(shared: true, completion: { self?.dismiss?(true) diff --git a/submodules/ShareItems/Sources/ShareItems.swift b/submodules/ShareItems/Sources/ShareItems.swift index d0bad3b932..f61b926064 100644 --- a/submodules/ShareItems/Sources/ShareItems.swift +++ b/submodules/ShareItems/Sources/ShareItems.swift @@ -459,11 +459,11 @@ public func sentShareItems(account: Account, to peerIds: [PeerId], items: [Prepa for item in items { switch item { case let .text(text): - messages.append(.message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) case let .media(media): switch media { case let .media(reference): - let message: EnqueueMessage = .message(text: "", attributes: attributes, mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil) messages.append(message) mediaMessages.append(message) diff --git a/submodules/ShimmerEffect/Sources/ShimmerEffect.swift b/submodules/ShimmerEffect/Sources/ShimmerEffect.swift index e2827e4ea2..311a5ac2c7 100644 --- a/submodules/ShimmerEffect/Sources/ShimmerEffect.swift +++ b/submodules/ShimmerEffect/Sources/ShimmerEffect.swift @@ -430,3 +430,69 @@ public final class ShimmerEffectNode: ASDisplayNode { self.effectNode.frame = CGRect(origin: CGPoint(), size: size) } } + +public final class StandaloneShimmerEffect { + private var image: UIImage? + + private var background: UIColor? + private var foreground: UIColor? + + public var layer: CALayer? { + didSet { + if self.layer !== oldValue { + self.updateLayer() + } + } + } + + public init() { + } + + public func update(background: UIColor, foreground: UIColor) { + if self.background == background && self.foreground == foreground { + return + } + self.background = background + self.foreground = foreground + + self.image = generateImage(CGSize(width: 1.0, height: 320.0), opaque: false, scale: 1.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(background.cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + + context.clip(to: CGRect(origin: CGPoint(), size: size)) + + let transparentColor = foreground.withAlphaComponent(0.0).cgColor + let peakColor = foreground.cgColor + + var locations: [CGFloat] = [0.0, 0.5, 1.0] + let colors: [CGColor] = [transparentColor, peakColor, transparentColor] + + let colorSpace = CGColorSpaceCreateDeviceRGB() + let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + }) + + self.updateLayer() + } + + public func updateLayer() { + guard let layer = self.layer, let image = self.image else { + return + } + + layer.contents = image.cgImage + + if layer.animation(forKey: "shimmer") == nil { + let animation = CABasicAnimation(keyPath: "contentsRect.origin.y") + animation.fromValue = 1.0 as NSNumber + animation.toValue = -1.0 as NSNumber + animation.isAdditive = true + animation.repeatCount = .infinity + animation.duration = 0.8 + animation.beginTime = layer.convertTime(1.0, from: nil) + layer.add(animation, forKey: "shimmer") + } + } +} diff --git a/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift b/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift index 61c29e57a6..2835c10c6d 100644 --- a/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift +++ b/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift @@ -21,8 +21,8 @@ private func decodeStickerThumbnailData(_ data: Data) -> String { return string } -public func generateStickerPlaceholderImage(data: Data?, size: CGSize, imageSize: CGSize, backgroundColor: UIColor?, foregroundColor: UIColor) -> UIImage? { - return generateImage(size, rotatedContext: { size, context in +public func generateStickerPlaceholderImage(data: Data?, size: CGSize, scale: CGFloat? = nil, imageSize: CGSize, backgroundColor: UIColor?, foregroundColor: UIColor) -> UIImage? { + return generateImage(size, scale: scale, rotatedContext: { size, context in if let backgroundColor = backgroundColor { context.setFillColor(backgroundColor.cgColor) context.setBlendMode(.copy) diff --git a/submodules/SoftwareVideo/Sources/SampleBufferPool.swift b/submodules/SoftwareVideo/Sources/SampleBufferPool.swift index 1bc235682e..da15e330a1 100644 --- a/submodules/SoftwareVideo/Sources/SampleBufferPool.swift +++ b/submodules/SoftwareVideo/Sources/SampleBufferPool.swift @@ -18,7 +18,6 @@ public final class SampleBufferLayer { public let layer: AVSampleBufferDisplayLayer private let enqueue: (AVSampleBufferDisplayLayer) -> Void - public var isFreed: Bool = false fileprivate init(layer: AVSampleBufferDisplayLayer, enqueue: @escaping (AVSampleBufferDisplayLayer) -> Void) { self.layer = layer diff --git a/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift b/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift index e085159f60..0e7d528b9f 100644 --- a/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift +++ b/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift @@ -5,6 +5,7 @@ import TelegramCore import SwiftSignalKit import CoreMedia import UniversalMediaPlayer +import AVFoundation public let softwareVideoApplyQueue = Queue() public let softwareVideoWorkers = ThreadPool(threadCount: 3, threadPriority: 0.2) @@ -25,7 +26,8 @@ public final class SoftwareVideoLayerFrameManager { private let resource: MediaResource private let secondaryResource: MediaResource? private let queue: ThreadPoolQueue - private let layerHolder: SampleBufferLayer + private let layerHolder: SampleBufferLayer? + private weak var layer: AVSampleBufferDisplayLayer? private var rotationAngle: CGFloat = 0.0 private var aspect: CGFloat = 1.0 @@ -33,9 +35,9 @@ public final class SoftwareVideoLayerFrameManager { private var layerRotationAngleAndAspect: (CGFloat, CGFloat)? private var didStart = false - var started: () -> Void = { } + public var started: () -> Void = { } - public init(account: Account, fileReference: FileMediaReference, layerHolder: SampleBufferLayer, hintVP9: Bool = false) { + public init(account: Account, fileReference: FileMediaReference, layerHolder: SampleBufferLayer?, layer: AVSampleBufferDisplayLayer? = nil, hintVP9: Bool = false) { var resource = fileReference.media.resource var secondaryResource: MediaResource? for attribute in fileReference.media.attributes { @@ -54,8 +56,9 @@ public final class SoftwareVideoLayerFrameManager { self.secondaryResource = secondaryResource self.queue = ThreadPoolQueue(threadPool: softwareVideoWorkers) self.layerHolder = layerHolder - layerHolder.layer.videoGravity = .resizeAspectFill - layerHolder.layer.masksToBounds = true + self.layer = layer ?? layerHolder?.layer + self.layer?.videoGravity = .resizeAspectFill + self.layer?.masksToBounds = true self.fetchDisposable = fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: fileReference.resourceReference(resource)).start() } @@ -113,7 +116,7 @@ public final class SoftwareVideoLayerFrameManager { let size = fileSize(path) Logger.shared.log("SoftwareVideo", "loaded video from \(stringForResource(resource)) (file size: \(String(describing: size))") - let _ = strongSelf.source.swap(SoftwareVideoSource(path: path, hintVP9: strongSelf.hintVP9)) + let _ = strongSelf.source.swap(SoftwareVideoSource(path: path, hintVP9: strongSelf.hintVP9, unpremultiplyAlpha: true)) } })) } @@ -139,8 +142,8 @@ public final class SoftwareVideoLayerFrameManager { for i in (0 ... latestFrameIndex).reversed() { self.frames.remove(at: i) } - if self.layerHolder.layer.status == .failed { - self.layerHolder.layer.flush() + if self.layer?.status == .failed { + self.layer?.flush() } /*if self.layerRotationAngleAndAspect?.0 != self.rotationAngle || self.layerRotationAngleAndAspect?.1 != self.aspect { self.layerRotationAngleAndAspect = (self.rotationAngle, self.aspect) @@ -150,7 +153,7 @@ public final class SoftwareVideoLayerFrameManager { } self.layerHolder.layer.setAffineTransform(transform) }*/ - self.layerHolder.layer.enqueue(frame.sampleBuffer) + self.layer?.enqueue(frame.sampleBuffer) if !self.didStart { self.didStart = true diff --git a/submodules/StatisticsUI/Sources/StatsMessageItem.swift b/submodules/StatisticsUI/Sources/StatsMessageItem.swift index d9c9471f5a..a3725e2a84 100644 --- a/submodules/StatisticsUI/Sources/StatsMessageItem.swift +++ b/submodules/StatisticsUI/Sources/StatsMessageItem.swift @@ -242,7 +242,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode { let presentationData = item.context.sharedContext.currentPresentationData.with { $0 } let contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId) - var text = !item.message.text.isEmpty ? item.message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0 + var text = !item.message.text.isEmpty ? item.message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0.string text = foldLineBreaks(text) var contentImageMedia: Media? diff --git a/submodules/StickerPackPreviewUI/BUILD b/submodules/StickerPackPreviewUI/BUILD index 78d84217e6..12812342de 100644 --- a/submodules/StickerPackPreviewUI/BUILD +++ b/submodules/StickerPackPreviewUI/BUILD @@ -35,6 +35,10 @@ swift_library( "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", "//submodules/PremiumUI:PremiumUI", "//submodules/OverlayStatusController:OverlayStatusController", + "//submodules/TelegramUI/Components/EntityKeyboard:EntityKeyboard", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/StickerPeekUI:StickerPeekUI", ], visibility = [ "//visibility:public", diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift new file mode 100644 index 0000000000..b43be1d5c7 --- /dev/null +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -0,0 +1,394 @@ +import Foundation +import UIKit +import Display +import TelegramCore +import SwiftSignalKit +import AsyncDisplayKit +import Postbox +import StickerResources +import AccountContext +import AnimatedStickerNode +import TelegramAnimatedStickerNode +import TelegramPresentationData +import ShimmerEffect +import EntityKeyboard +import AnimationCache +import MultiAnimationRenderer + +private let nativeItemSize = 36.0 +private let minItemsPerRow = 8 +private let verticalSpacing = 9.0 +private let minSpacing = 9.0 +private let containerInsets = UIEdgeInsets(top: 0.0, left: 12.0, bottom: 0.0, right: 12.0) + +class ItemLayout { + let width: CGFloat + let itemsCount: Int + let hasTitle: Bool + let itemsPerRow: Int + let visibleItemSize: CGFloat + let horizontalSpacing: CGFloat + let itemTopOffset: CGFloat + let height: CGFloat + + init(width: CGFloat, itemsCount: Int, hasTitle: Bool) { + self.width = width + self.itemsCount = itemsCount + self.hasTitle = hasTitle + + let itemHorizontalSpace = width - containerInsets.left - containerInsets.right + self.itemsPerRow = max(minItemsPerRow, Int((itemHorizontalSpace + minSpacing) / (nativeItemSize + minSpacing))) + + self.visibleItemSize = floor((itemHorizontalSpace - CGFloat(self.itemsPerRow - 1) * minSpacing) / CGFloat(self.itemsPerRow)) + + self.horizontalSpacing = floor((itemHorizontalSpace - visibleItemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) + + let numRowsInGroup = (itemsCount + (self.itemsPerRow - 1)) / self.itemsPerRow + + self.itemTopOffset = hasTitle ? 61.0 : 0.0 + self.height = itemTopOffset + CGFloat(numRowsInGroup) * visibleItemSize + CGFloat(max(0, numRowsInGroup - 1)) * verticalSpacing + } + + func frame(itemIndex: Int) -> CGRect { + let row = itemIndex / self.itemsPerRow + let column = itemIndex % self.itemsPerRow + + return CGRect( + origin: CGPoint( + x: containerInsets.left + CGFloat(column) * (self.visibleItemSize + self.horizontalSpacing), + y: self.itemTopOffset + CGFloat(row) * (self.visibleItemSize + verticalSpacing) + ), + size: CGSize( + width: self.visibleItemSize, + height: self.visibleItemSize + ) + ) + } +} + +final class StickerPackEmojisItem: GridItem { + let context: AccountContext + let animationCache: AnimationCache + let animationRenderer: MultiAnimationRenderer + let interaction: StickerPackPreviewInteraction + let info: StickerPackCollectionInfo + let items: [StickerPackItem] + let theme: PresentationTheme + let strings: PresentationStrings + let title: String? + let isInstalled: Bool? + let isEmpty: Bool + + let section: GridSection? = nil + let fillsRowWithDynamicHeight: ((CGFloat) -> CGFloat)? + + init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, interaction: StickerPackPreviewInteraction, info: StickerPackCollectionInfo, items: [StickerPackItem], theme: PresentationTheme, strings: PresentationStrings, title: String?, isInstalled: Bool?, isEmpty: Bool) { + self.context = context + self.animationCache = animationCache + self.animationRenderer = animationRenderer + self.interaction = interaction + self.info = info + self.items = items + self.theme = theme + self.strings = strings + self.title = title + self.isInstalled = isInstalled + self.isEmpty = isEmpty + + self.fillsRowWithDynamicHeight = { width in + let layout = ItemLayout(width: width, itemsCount: items.count, hasTitle: title != nil) + return layout.height + } + } + + func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode { + let node = StickerPackEmojisItemNode() + return node + } + + func update(node: GridItemNode) { + guard let _ = node as? StickerPackEmojisItemNode else { + assertionFailure() + return + } + } +} + +private let textFont = Font.regular(20.0) + +final class StickerPackEmojisItemNode: GridItemNode { + private var item: StickerPackEmojisItem? + private var itemLayout: ItemLayout? + + private var shimmerHostView: PortalSourceView? + private var standaloneShimmerEffect: StandaloneShimmerEffect? + + private var boundsChangeTrackerLayer = SimpleLayer() + + private var visibleItemLayers: [EmojiPagerContentComponent.View.ItemLayer.Key: EmojiPagerContentComponent.View.ItemLayer] = [:] + private var visibleItemPlaceholderViews: [EmojiPagerContentComponent.View.ItemLayer.Key: EmojiPagerContentComponent.View.ItemPlaceholderView] = [:] + + private let titleNode: ImmediateTextNode + private let subtitleNode: ImmediateTextNode + private let buttonNode: HighlightableButtonNode + + override init() { + self.titleNode = ImmediateTextNode() + self.subtitleNode = ImmediateTextNode() + self.buttonNode = HighlightableButtonNode(pointerStyle: nil) + self.buttonNode.clipsToBounds = true + self.buttonNode.cornerRadius = 14.0 + + super.init() + + self.addSubnode(self.titleNode) + self.addSubnode(self.subtitleNode) + self.addSubnode(self.buttonNode) + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + } + + @objc private func buttonPressed() { + guard let item = self.item else { + return + } + + if item.isInstalled == true { + item.interaction.removeStickerPack(item.info) + } else { + item.interaction.addStickerPack(item.info, item.items) + } + } + + override var isVisibleInGrid: Bool { + didSet { + + } + } + + override func didLoad() { + super.didLoad() + + let shimmerHostView = PortalSourceView() + shimmerHostView.alpha = 0.0 + shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.size) + self.view.addSubview(shimmerHostView) + self.shimmerHostView = shimmerHostView + + let standaloneShimmerEffect = StandaloneShimmerEffect() + self.standaloneShimmerEffect = standaloneShimmerEffect + if let item = self.item { + let shimmerBackgroundColor = item.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08) + let shimmerForegroundColor = item.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) + standaloneShimmerEffect.update(background: shimmerBackgroundColor, foreground: shimmerForegroundColor) + self.updateShimmerIfNeeded() + } + + let boundsChangeTrackerLayer = SimpleLayer() + boundsChangeTrackerLayer.opacity = 0.0 + self.layer.addSublayer(boundsChangeTrackerLayer) + boundsChangeTrackerLayer.didEnterHierarchy = { [weak self] in + self?.standaloneShimmerEffect?.updateLayer() + } + self.boundsChangeTrackerLayer = boundsChangeTrackerLayer + } + + private var size = CGSize() + override func updateLayout(item: GridItem, size: CGSize, isVisible: Bool, synchronousLoads: Bool) { + guard let item = item as? StickerPackEmojisItem else { + return + } + self.item = item + self.size = size + + if let title = item.title { + let isInstalled = item.isInstalled ?? false + + self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(17.0), textColor: item.theme.actionSheet.primaryTextColor, paragraphAlignment: .natural) + self.subtitleNode.attributedText = NSAttributedString(string: item.strings.EmojiPack_Emoji(Int32(item.items.count)), font: Font.regular(15.0), textColor: item.theme.actionSheet.secondaryTextColor, paragraphAlignment: .natural) + + self.buttonNode.setAttributedTitle(NSAttributedString(string: isInstalled ? item.strings.EmojiPack_Added.uppercased() : item.strings.EmojiPack_Add.uppercased(), font: Font.semibold(15.0), textColor: isInstalled ? item.theme.list.itemCheckColors.fillColor : item.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center), for: .normal) + self.buttonNode.backgroundColor = isInstalled ? item.theme.list.itemCheckColors.fillColor.withAlphaComponent(0.08) : item.theme.list.itemCheckColors.fillColor + } + + self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) + + let shimmerBackgroundColor = item.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08) + let shimmerForegroundColor = item.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) + self.standaloneShimmerEffect?.update(background: shimmerBackgroundColor, foreground: shimmerForegroundColor) + + self.setNeedsLayout() + } + + func updateVisibleItems(attemptSynchronousLoads: Bool, transition: ContainedViewLayoutTransition) { + guard let item = self.item, !self.size.width.isZero else { + return + } + + let context = item.context + let animationCache = item.animationCache + let animationRenderer = item.animationRenderer + let theme = item.theme + let items = item.items + var validIds = Set() + + let itemLayout: ItemLayout + if let current = self.itemLayout, current.width == self.size.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) { + itemLayout = current + } else { + itemLayout = ItemLayout(width: self.size.width, itemsCount: items.count, hasTitle: item.title != nil) + self.itemLayout = itemLayout + } + + for index in 0 ..< items.count { + let item = items[index] + let itemId = EmojiPagerContentComponent.View.ItemLayer.Key(groupId: 0, fileId: item.file.fileId, staticEmoji: nil) + validIds.insert(itemId) + + let itemDimensions = item.file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0) + let itemNativeFitSize = itemDimensions.fitted(CGSize(width: nativeItemSize, height: nativeItemSize)) + let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + + var updateItemLayerPlaceholder = false + var itemTransition = transition + let itemLayer: EmojiPagerContentComponent.View.ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + updateItemLayerPlaceholder = true + itemTransition = .immediate + + itemLayer = EmojiPagerContentComponent.View.ItemLayer( + item: EmojiPagerContentComponent.Item(file: item.file, staticEmoji: nil, subgroupId: nil), + context: context, + attemptSynchronousLoad: attemptSynchronousLoads, + file: item.file, + staticEmoji: nil, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), + blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), + pointSize: itemNativeFitSize, + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in + guard let strongSelf = self else { + return + } + if displayPlaceholder { + if let itemLayer = strongSelf.visibleItemLayers[itemId] { + let placeholderView: EmojiPagerContentComponent.View.ItemPlaceholderView + if let current = strongSelf.visibleItemPlaceholderViews[itemId] { + placeholderView = current + } else { + placeholderView = EmojiPagerContentComponent.View.ItemPlaceholderView( + context: context, + file: item.file, + shimmerView: strongSelf.shimmerHostView, + color: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08), + size: itemNativeFitSize + ) + strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView + strongSelf.view.insertSubview(placeholderView, at: 0) + } + placeholderView.frame = itemLayer.frame + placeholderView.update(size: placeholderView.bounds.size) + + strongSelf.updateShimmerIfNeeded() + } + } else { + if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { + strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) + + if duration > 0.0 { + placeholderView.layer.opacity = 0.0 + placeholderView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, completion: { [weak self, weak placeholderView] _ in + guard let strongSelf = self else { + return + } + placeholderView?.removeFromSuperview() + strongSelf.updateShimmerIfNeeded() + }) + } else { + placeholderView.removeFromSuperview() + strongSelf.updateShimmerIfNeeded() + } + } + } + } + ) + self.layer.addSublayer(itemLayer) + self.visibleItemLayers[itemId] = itemLayer + } + + var itemFrame = itemLayout.frame(itemIndex: index) + + itemFrame.origin.x += floor((itemFrame.width - itemVisibleFitSize.width) / 2.0) + itemFrame.origin.y += floor((itemFrame.height - itemVisibleFitSize.height) / 2.0) + itemFrame.size = itemVisibleFitSize + + let itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) + itemTransition.updatePosition(layer: itemLayer, position: itemPosition) + itemTransition.updateBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + if let placeholderView = self.visibleItemPlaceholderViews[itemId] { + if placeholderView.layer.position != itemPosition || placeholderView.layer.bounds != itemBounds { + itemTransition.updateFrame(view: placeholderView, frame: itemFrame) + placeholderView.update(size: itemFrame.size) + } + } else if updateItemLayerPlaceholder { + if itemLayer.displayPlaceholder { + itemLayer.onUpdateDisplayPlaceholder(true, 0.0) + } + } + + itemLayer.isVisibleForAnimations = true + } + + for id in self.visibleItemLayers.keys { + if !validIds.contains(id) { + self.visibleItemLayers[id]?.removeFromSuperlayer() + self.visibleItemLayers[id] = nil + } + } + for id in self.visibleItemPlaceholderViews.keys { + if !validIds.contains(id) { + self.visibleItemPlaceholderViews[id]?.removeFromSuperview() + self.visibleItemPlaceholderViews[id] = nil + } + } + } + + private func updateShimmerIfNeeded() { + if self.visibleItemPlaceholderViews.isEmpty { + self.standaloneShimmerEffect?.layer = nil + } else { + self.standaloneShimmerEffect?.layer = self.shimmerHostView?.layer + } + } + + override func layout() { + super.layout() + + if let _ = self.item { + var buttonSize = self.buttonNode.calculateSizeThatFits(self.size) + buttonSize.width += 24.0 + buttonSize.height = 28.0 + + let titleSize = self.titleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height)) + let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.size.width - 60.0, height: self.size.height)) + + self.titleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 10.0), size: titleSize) + self.subtitleNode.frame = CGRect(origin: CGPoint(x: 16.0, y: 33.0), size: subtitleSize) + + self.buttonNode.frame = CGRect(origin: CGPoint(x: self.size.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize) + } + + self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.size) + self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) + } + + func transitionNode() -> ASDisplayNode? { + return self + } +} + diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift index 3c598121cf..482a6dc37c 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewController.swift @@ -48,12 +48,12 @@ public final class StickerPackPreviewController: ViewController, StandalonePrese private var presentationData: PresentationData private var presentationDataDisposable: Disposable? - public var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? { + public var sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? { didSet { if self.isNodeLoaded { if let sendSticker = self.sendSticker { - self.controllerNode.sendSticker = { [weak self] file, sourceNode, sourceRect in - if sendSticker(file, sourceNode, sourceRect) { + self.controllerNode.sendSticker = { [weak self] file, sourceView, sourceRect in + if sendSticker(file, sourceView, sourceRect) { self?.dismiss() return true } else { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index c5bcd464cb..81ac844056 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -12,6 +12,7 @@ import ActivityIndicator import TextFormat import AccountContext import ContextUI +import StickerPeekUI private struct StickerPackPreviewGridEntry: Comparable, Identifiable { let index: Int @@ -73,7 +74,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol var presentInGlobalOverlay: ((ViewController, Any?) -> Void)? var dismiss: (() -> Void)? var cancel: (() -> Void)? - var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + var sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private let actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? let ready = Promise() @@ -142,7 +143,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol super.init() - self.interaction = StickerPackPreviewInteraction(playAnimatedStickers: false) + self.interaction = StickerPackPreviewInteraction(playAnimatedStickers: false, addStickerPack: { _, _ in }, removeStickerPack: { _ in }) self.backgroundColor = nil self.isOpaque = false @@ -197,7 +198,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.wrappingScrollNode.view.contentInsetAdjustmentBehavior = .never } - self.contentGridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>? in + self.contentGridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError>? in if let strongSelf = self { if let itemNode = strongSelf.contentGridNode.itemNodeAtPoint(point) as? StickerPackPreviewGridItemNode, let item = itemNode.stickerPackItem { let accountPeerId = strongSelf.context.account.peerId @@ -212,7 +213,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol } ) |> deliverOnMainQueue - |> map { isStarred, hasPremium -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred, hasPremium -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] if let stickerPack = strongSelf.stickerPack, case let .result(info, _, _) = stickerPack, info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { @@ -220,9 +221,9 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol menuItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode, imageNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode.view, imageNode.bounds) } } f(.default) @@ -238,7 +239,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol } }))) } - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { })) } else { @@ -248,10 +249,10 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { - let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) controller.visibilityUpdated = { [weak self] visible in if let strongSelf = self { @@ -399,7 +400,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol if self.currentItems.isEmpty && !updatedItems.isEmpty { let entities = generateTextEntities(info.title, enabledTypes: [.mention]) let font = Font.medium(20.0) - self.contentTitleNode.attributedText = stringWithAppliedEntities(info.title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: font, linkFont: font, boldFont: font, italicFont: font, boldItalicFont: font, fixedFont: font, blockQuoteFont: font) + self.contentTitleNode.attributedText = stringWithAppliedEntities(info.title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: font, linkFont: font, boldFont: font, italicFont: font, boldItalicFont: font, fixedFont: font, blockQuoteFont: font, message: nil) animateIn = true } transaction = StickerPackPreviewGridTransaction(previousList: self.currentItems, list: updatedItems, account: self.context.account, interaction: self.interaction, theme: self.presentationData.theme) @@ -620,6 +621,8 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol let text: String if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { text = self.presentationData.strings.StickerPack_RemoveStickerCount(info.count) + } else if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + text = self.presentationData.strings.StickerPack_RemoveEmojiCount(info.count) } else { text = self.presentationData.strings.StickerPack_RemoveMaskCount(info.count) } @@ -628,6 +631,8 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol let text: String if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { text = self.presentationData.strings.StickerPack_AddStickerCount(info.count) + } else if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + text = self.presentationData.strings.StickerPack_AddEmojiCount(info.count) } else { text = self.presentationData.strings.StickerPack_AddMaskCount(info.count) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift index 6009f7e493..e9805d04c4 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift @@ -11,13 +11,19 @@ import AnimatedStickerNode import TelegramAnimatedStickerNode import TelegramPresentationData import ShimmerEffect +import StickerPeekUI final class StickerPackPreviewInteraction { var previewedItem: StickerPreviewPeekItem? var playAnimatedStickers: Bool - init(playAnimatedStickers: Bool) { + let addStickerPack: (StickerPackCollectionInfo, [StickerPackItem]) -> Void + let removeStickerPack: (StickerPackCollectionInfo) -> Void + + init(playAnimatedStickers: Bool, addStickerPack: @escaping (StickerPackCollectionInfo, [StickerPackItem]) -> Void, removeStickerPack: @escaping (StickerPackCollectionInfo) -> Void) { self.playAnimatedStickers = playAnimatedStickers + self.addStickerPack = addStickerPack + self.removeStickerPack = removeStickerPack } } @@ -186,7 +192,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode { lockBackground.isUserInteractionEnabled = false lockIconNode = ASImageNode() lockIconNode.displaysAsynchronously = false - lockIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: .white) + lockIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) let lockTintView = UIView() lockTintView.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.15) @@ -315,8 +321,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode { } if let lockBackground = self.lockBackground, let lockTintView = self.lockTintView, let lockIconNode = self.lockIconNode { - let lockSize = CGSize(width: 30.0, height: 30.0) - let lockBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - lockSize.width) / 2.0), y: bounds.height - lockSize.height - 6.0), size: lockSize) + let lockSize = CGSize(width: 16.0, height: 16.0) + let lockBackgroundFrame = CGRect(origin: CGPoint(x: bounds.width - lockSize.width, y: bounds.height - lockSize.height), size: lockSize) lockBackground.frame = lockBackgroundFrame lockBackground.layer.cornerRadius = lockSize.width / 2.0 if #available(iOS 13.0, *) { @@ -324,7 +330,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode { } lockTintView.frame = CGRect(origin: CGPoint(), size: lockBackgroundFrame.size) if let icon = lockIconNode.image { - lockIconNode.frame = CGRect(origin: CGPoint(x: lockBackgroundFrame.minX + floorToScreenPixels((lockBackgroundFrame.width - icon.size.width) / 2.0), y: lockBackgroundFrame.minY + floorToScreenPixels((lockBackgroundFrame.height - icon.size.height) / 2.0)), size: icon.size) + let iconSize = CGSize(width: icon.size.width - 4.0, height: icon.size.height - 4.0) + lockIconNode.frame = CGRect(origin: CGPoint(x: lockBackgroundFrame.minX + floorToScreenPixels((lockBackgroundFrame.width - iconSize.width) / 2.0), y: lockBackgroundFrame.minY + floorToScreenPixels((lockBackgroundFrame.height - iconSize.height) / 2.0)), size: iconSize) } } } @@ -343,7 +350,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode { func updatePreviewing(animated: Bool) { var isPreviewing = false if let (_, maybeItem) = self.currentState, let interaction = self.interaction, let item = maybeItem { - isPreviewing = interaction.previewedItem == .pack(item) + isPreviewing = interaction.previewedItem == .pack(item.file) } if self.currentIsPreviewing != isPreviewing { self.currentIsPreviewing = isPreviewing diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 04b7b114c5..96786183cb 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -18,14 +18,20 @@ import TextFormat import PremiumUI import OverlayStatusController import PresentationDataUtils +import StickerPeekUI +import AnimationCache +import MultiAnimationRenderer private enum StickerPackPreviewGridEntry: Comparable, Identifiable { case sticker(index: Int, stableId: Int, stickerItem: StickerPackItem?, isEmpty: Bool, isPremium: Bool, isLocked: Bool) + case emojis(index: Int, stableId: Int, info: StickerPackCollectionInfo, items: [StickerPackItem], title: String?, isInstalled: Bool?) var stableId: Int { switch self { case let .sticker(_, stableId, _, _, _, _): return stableId + case let .emojis(_, stableId, _, _, _, _): + return stableId } } @@ -33,6 +39,8 @@ private enum StickerPackPreviewGridEntry: Comparable, Identifiable { switch self { case let .sticker(index, _, _, _, _, _): return index + case let .emojis(index, _, _, _, _, _): + return index } } @@ -40,10 +48,12 @@ private enum StickerPackPreviewGridEntry: Comparable, Identifiable { return lhs.index < rhs.index } - func item(account: Account, interaction: StickerPackPreviewInteraction, theme: PresentationTheme, strings: PresentationStrings) -> GridItem { + func item(context: AccountContext, interaction: StickerPackPreviewInteraction, theme: PresentationTheme, strings: PresentationStrings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer) -> GridItem { switch self { case let .sticker(_, _, stickerItem, isEmpty, isPremium, isLocked): - return StickerPackPreviewGridItem(account: account, stickerItem: stickerItem, interaction: interaction, theme: theme, isPremium: isPremium, isLocked: isLocked, isEmpty: isEmpty) + return StickerPackPreviewGridItem(account: context.account, stickerItem: stickerItem, interaction: interaction, theme: theme, isPremium: isPremium, isLocked: isLocked, isEmpty: isEmpty) + case let .emojis(_, _, info, items, title, isInstalled): + return StickerPackEmojisItem(context: context, animationCache: animationCache, animationRenderer: animationRenderer, interaction: interaction, info: info, items: items, theme: theme, strings: strings, title: title, isInstalled: isInstalled, isEmpty: false) } } } @@ -54,12 +64,12 @@ private struct StickerPackPreviewGridTransaction { let updates: [GridNodeUpdateItem] let scrollToItem: GridNodeScrollToItem? - init(previousList: [StickerPackPreviewGridEntry], list: [StickerPackPreviewGridEntry], account: Account, interaction: StickerPackPreviewInteraction, theme: PresentationTheme, strings: PresentationStrings, scrollToItem: GridNodeScrollToItem?) { + init(previousList: [StickerPackPreviewGridEntry], list: [StickerPackPreviewGridEntry], context: AccountContext, interaction: StickerPackPreviewInteraction, theme: PresentationTheme, strings: PresentationStrings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, scrollToItem: GridNodeScrollToItem?) { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: previousList, rightList: list) self.deletions = deleteIndices - self.insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(account: account, interaction: interaction, theme: theme, strings: strings), previousIndex: $0.2) } - self.updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction, theme: theme, strings: strings)) } + self.insertions = indicesAndItems.map { GridNodeInsertItem(index: $0.0, item: $0.1.item(context: context, interaction: interaction, theme: theme, strings: strings, animationCache: animationCache, animationRenderer: animationRenderer), previousIndex: $0.2) } + self.updates = updateIndices.map { GridNodeUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, interaction: interaction, theme: theme, strings: strings, animationCache: animationCache, animationRenderer: animationRenderer)) } self.scrollToItem = scrollToItem } @@ -81,11 +91,11 @@ private final class StickerPackContainer: ASDisplayNode { private let context: AccountContext private weak var controller: StickerPackScreenImpl? private var presentationData: PresentationData - private let stickerPack: StickerPackReference + private let stickerPacks: [StickerPackReference] private let decideNextAction: (StickerPackContainer, StickerPackAction) -> StickerPackNextAction private let requestDismiss: () -> Void private let presentInGlobalOverlay: (ViewController, Any?) -> Void - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private let backgroundNode: ASImageNode private let gridNode: GridNode private let actionAreaBackgroundNode: NavigationBackgroundNode @@ -108,7 +118,9 @@ private final class StickerPackContainer: ASDisplayNode { private var enqueuedTransactions: [StickerPackPreviewGridTransaction] = [] private var itemsDisposable: Disposable? + private var currentContents: [LoadedStickerPack]? private(set) var currentStickerPack: (StickerPackCollectionInfo, [StickerPackItem], Bool)? + private(set) var currentStickerPacks: [(StickerPackCollectionInfo, [StickerPackItem], Bool)] = [] private var didReceiveStickerPackResult = false private let isReadyValue = Promise() @@ -129,12 +141,16 @@ private final class StickerPackContainer: ASDisplayNode { private weak var peekController: PeekController? - init(index: Int, context: AccountContext, presentationData: PresentationData, stickerPack: StickerPackReference, decideNextAction: @escaping (StickerPackContainer, StickerPackAction) -> StickerPackNextAction, requestDismiss: @escaping () -> Void, expandProgressUpdated: @escaping (StickerPackContainer, ContainedViewLayoutTransition, ContainedViewLayoutTransition) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, openMention: @escaping (String) -> Void, controller: StickerPackScreenImpl?) { + var onLoading: () -> Void = {} + var onReady: () -> Void = {} + var onError: () -> Void = {} + + init(index: Int, context: AccountContext, presentationData: PresentationData, stickerPacks: [StickerPackReference], decideNextAction: @escaping (StickerPackContainer, StickerPackAction) -> StickerPackNextAction, requestDismiss: @escaping () -> Void, expandProgressUpdated: @escaping (StickerPackContainer, ContainedViewLayoutTransition, ContainedViewLayoutTransition) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, openMention: @escaping (String) -> Void, controller: StickerPackScreenImpl?) { self.index = index self.context = context self.controller = controller self.presentationData = presentationData - self.stickerPack = stickerPack + self.stickerPacks = stickerPacks self.decideNextAction = decideNextAction self.requestDismiss = requestDismiss self.presentInGlobalOverlay = presentInGlobalOverlay @@ -183,7 +199,13 @@ private final class StickerPackContainer: ASDisplayNode { self.moreButtonNode = MoreButtonNode(theme: self.presentationData.theme) self.moreButtonNode.iconNode.enqueueState(.more, animated: false) - self.interaction = StickerPackPreviewInteraction(playAnimatedStickers: true) + var addStickerPackImpl: ((StickerPackCollectionInfo, [StickerPackItem]) -> Void)? + var removeStickerPackImpl: ((StickerPackCollectionInfo) -> Void)? + self.interaction = StickerPackPreviewInteraction(playAnimatedStickers: true, addStickerPack: { info, items in + addStickerPackImpl?(info, items) + }, removeStickerPack: { info in + removeStickerPackImpl?(info) + }) super.init() @@ -301,7 +323,11 @@ private final class StickerPackContainer: ASDisplayNode { return updatedOffset } - self.itemsDisposable = combineLatest(queue: Queue.mainQueue(), context.engine.stickers.loadedStickerPack(reference: stickerPack, forceActualized: false), context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))).start(next: { [weak self] contents, peer in + let loadedStickerPacks = combineLatest(stickerPacks.map { + context.engine.stickers.loadedStickerPack(reference: $0, forceActualized: true) + }) + + self.itemsDisposable = combineLatest(queue: Queue.mainQueue(), loadedStickerPacks, context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))).start(next: { [weak self] contents, peer in guard let strongSelf = self else { return } @@ -335,6 +361,40 @@ private final class StickerPackContainer: ASDisplayNode { } self.titleNode.linkHighlightColor = self.presentationData.theme.actionSheet.controlAccentColor.withAlphaComponent(0.5) + + addStickerPackImpl = { [weak self] info, items in + guard let strongSelf = self else { + return + } + if let index = strongSelf.currentStickerPacks.firstIndex(where: { $0.0.id == info.id }) { + strongSelf.currentStickerPacks[index].2 = true + + var contents: [LoadedStickerPack] = [] + for (info, items, isInstalled) in strongSelf.currentStickerPacks { + contents.append(.result(info: info, items: items, installed: isInstalled)) + } + strongSelf.updateStickerPackContents(contents, hasPremium: false) + + let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() + } + } + + removeStickerPackImpl = { [weak self] info in + guard let strongSelf = self else { + return + } + if let index = strongSelf.currentStickerPacks.firstIndex(where: { $0.0.id == info.id }) { + strongSelf.currentStickerPacks[index].2 = false + + var contents: [LoadedStickerPack] = [] + for (info, items, isInstalled) in strongSelf.currentStickerPacks { + contents.append(.result(info: info, items: items, installed: isInstalled)) + } + strongSelf.updateStickerPackContents(contents, hasPremium: false) + + let _ = strongSelf.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete).start() + } + } } deinit { @@ -344,7 +404,7 @@ private final class StickerPackContainer: ASDisplayNode { override func didLoad() { super.didLoad() - self.gridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>? in + self.gridNode.view.addGestureRecognizer(PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point -> Signal<(UIView, CGRect, PeekControllerContent)?, NoError>? in if let strongSelf = self { if let itemNode = strongSelf.gridNode.itemNodeAtPoint(point) as? StickerPackPreviewGridItemNode, let item = itemNode.stickerPackItem { let accountPeerId = strongSelf.context.account.peerId @@ -359,7 +419,7 @@ private final class StickerPackContainer: ASDisplayNode { } ) |> deliverOnMainQueue - |> map { isStarred, hasPremium -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred, hasPremium -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] if let (info, _, _) = strongSelf.currentStickerPack, info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { @@ -367,9 +427,9 @@ private final class StickerPackContainer: ASDisplayNode { menuItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode, imageNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode.view, imageNode.bounds) } } f(.default) @@ -385,7 +445,7 @@ private final class StickerPackContainer: ASDisplayNode { } }))) } - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -401,10 +461,10 @@ private final class StickerPackContainer: ASDisplayNode { } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { - let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) controller.visibilityUpdated = { [weak self] visible in if let strongSelf = self { @@ -442,7 +502,7 @@ private final class StickerPackContainer: ASDisplayNode { self.titleNode.linkHighlightColor = self.presentationData.theme.actionSheet.controlAccentColor.withAlphaComponent(0.5) - if let currentContents = self.currentContents { + if let currentContents = self.currentContents?.first { let buttonColor: UIColor var buttonFont: UIFont = Font.semibold(17.0) switch currentContents { @@ -459,15 +519,15 @@ private final class StickerPackContainer: ASDisplayNode { self.buttonNode.setTitle(self.buttonNode.attributedTitle(for: .normal)?.string ?? "", with: buttonFont, with: buttonColor, for: .normal) } - if !self.currentEntries.isEmpty { - let transaction = StickerPackPreviewGridTransaction(previousList: self.currentEntries, list: self.currentEntries, account: self.context.account, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, scrollToItem: nil) + if !self.currentEntries.isEmpty, let controller = self.controller { + let transaction = StickerPackPreviewGridTransaction(previousList: self.currentEntries, list: self.currentEntries, context: self.context, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, animationCache: controller.animationCache, animationRenderer: controller.animationRenderer, scrollToItem: nil) self.enqueueTransaction(transaction) } let titleFont = Font.semibold(17.0) let title = self.titleNode.attributedText?.string ?? "" let entities = generateTextEntities(title, enabledTypes: [.mention]) - self.titleNode.attributedText = stringWithAppliedEntities(title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont) + self.titleNode.attributedText = stringWithAppliedEntities(title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont, message: nil) if let (layout, _, _, _) = self.validLayout { let _ = self.titleNode.updateLayout(CGSize(width: layout.size.width - max(12.0, self.cancelButtonNode.frame.width) * 2.0 - 40.0, height: .greatestFiniteMagnitude)) @@ -476,12 +536,37 @@ private final class StickerPackContainer: ASDisplayNode { } @objc private func morePressed(node: ContextReferenceContentNode, gesture: ContextGesture?) { - guard let controller = self.controller, let (info, _, _) = self.currentStickerPack else { + guard let controller = self.controller else { return } let strings = self.presentationData.strings - let link = "https://t.me/addstickers/\(info.shortName)" + let text: String + let shareSubject: ShareControllerSubject + if !self.currentStickerPacks.isEmpty { + var links: String = "" + for (info, _, _) in self.currentStickerPacks { + if !links.isEmpty { + links += "\n" + } + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + links += "https://t.me/addemoji/\(info.shortName)" + } else { + links += "https://t.me/addstickers/\(info.shortName)" + } + } + text = links + shareSubject = .text(text) + } else if let (info, _, _) = self.currentStickerPack { + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + text = "https://t.me/addemoji/\(info.shortName)" + } else { + text = "https://t.me/addstickers/\(info.shortName)" + } + shareSubject = .url(text) + } else { + return + } var items: [ContextMenuItem] = [] items.append(.action(ContextMenuActionItem(text: strings.StickerPack_Share, icon: { theme in @@ -491,7 +576,7 @@ private final class StickerPackContainer: ASDisplayNode { if let strongSelf = self { let parentNavigationController = strongSelf.controller?.parentNavigationController - let shareController = ShareController(context: strongSelf.context, subject: .url(link)) + let shareController = ShareController(context: strongSelf.context, subject: shareSubject) shareController.actionCompleted = { [weak parentNavigationController] in if let parentNavigationController = parentNavigationController, let controller = parentNavigationController.topViewController as? ViewController { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } @@ -501,16 +586,19 @@ private final class StickerPackContainer: ASDisplayNode { strongSelf.controller?.present(shareController, in: .window(.root)) } }))) - items.append(.action(ContextMenuActionItem(text: strings.StickerPack_CopyLink, icon: { theme in + + let copyTitle = self.currentStickerPacks.count > 1 ? strings.StickerPack_CopyLinks : strings.StickerPack_CopyLink + let copyText = self.currentStickerPacks.count > 1 ? strings.Conversation_LinksCopied : strings.Conversation_LinkCopied + items.append(.action(ContextMenuActionItem(text: copyTitle, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) - UIPasteboard.general.string = link + UIPasteboard.general.string = text if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) + strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: copyText), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) } }))) @@ -523,45 +611,68 @@ private final class StickerPackContainer: ASDisplayNode { } @objc func buttonPressed() { - guard let (info, items, installed) = self.currentStickerPack else { - self.requestDismiss() - return - } - - let _ = (self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.stickerSettings]) - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] sharedData in - guard let strongSelf = self else { - return + if !self.currentStickerPacks.isEmpty { + var installedCount = 0 + for (_, _, isInstalled) in self.currentStickerPacks { + if isInstalled { + installedCount += 1 + } } + if installedCount == self.currentStickerPacks.count { + for (info, _, _) in self.currentStickerPacks { + let _ = (self.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete) + |> deliverOnMainQueue).start(next: { _ in +// guard let (positionInList, _) = indexAndItems else { +// return +// } +// if dismissed { +// actionPerformed?(info, items, .remove(positionInList: positionInList)) +// } + }) + } + } else { + var installedPacks: [(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)] = [] + for (info, items, isInstalled) in self.currentStickerPacks { + if !isInstalled { + installedPacks.append((info, items, .add)) + let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() + } + } + + self.controller?.actionPerformed?(installedPacks) + } + self.requestDismiss() + } else if let (info, items, installed) = self.currentStickerPack { var dismissed = false - switch strongSelf.decideNextAction(strongSelf, installed ? .remove : .add) { + switch self.decideNextAction(self, installed ? .remove : .add) { case .dismiss: - strongSelf.requestDismiss() + self.requestDismiss() dismissed = true case .navigatedNext, .ignored: - strongSelf.updateStickerPackContents(.result(info: info, items: items, installed: !installed), hasPremium: false) + self.updateStickerPackContents([.result(info: info, items: items, installed: !installed)], hasPremium: false) } - let actionPerformed = strongSelf.controller?.actionPerformed + let actionPerformed = self.controller?.actionPerformed if installed { - let _ = (strongSelf.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete) + let _ = (self.context.engine.stickers.removeStickerPackInteractively(id: info.id, option: .delete) |> deliverOnMainQueue).start(next: { indexAndItems in guard let (positionInList, _) = indexAndItems else { return } if dismissed { - actionPerformed?(info, items, .remove(positionInList: positionInList)) + actionPerformed?([(info, items, .remove(positionInList: positionInList))]) } }) } else { - let _ = strongSelf.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() + let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() if dismissed { - actionPerformed?(info, items, .add) + actionPerformed?([(info, items, .add)]) } } - }) + } else { + self.requestDismiss() + } } private func updateButtonBackgroundAlpha() { @@ -579,12 +690,7 @@ private final class StickerPackContainer: ASDisplayNode { self.actionAreaSeparatorNode.alpha = backgroundAlpha } - var onLoading: () -> Void = {} - var onReady: () -> Void = {} - var onError: () -> Void = {} - - private var currentContents: LoadedStickerPack? - private func updateStickerPackContents(_ contents: LoadedStickerPack, hasPremium: Bool) { + private func updateStickerPackContents(_ contents: [LoadedStickerPack], hasPremium: Bool) { self.currentContents = contents self.didReceiveStickerPackResult = true @@ -593,135 +699,208 @@ private final class StickerPackContainer: ASDisplayNode { var updateLayout = false var scrollToItem: GridNodeScrollToItem? + let titleFont = Font.semibold(17.0) - switch contents { - case .fetching: + if contents.count > 1 { self.onLoading() - entries = [] - self.buttonNode.setTitle(self.presentationData.strings.Channel_NotificationLoading, with: Font.semibold(17.0), with: self.presentationData.theme.list.itemDisabledTextColor, for: .normal) - self.buttonNode.setBackgroundImage(nil, for: []) - for _ in 0 ..< 16 { - var stableId: Int? - inner: for entry in self.currentEntries { - if case let .sticker(index, currentStableId, stickerItem, _, _, _) = entry, stickerItem == nil, index == entries.count { - stableId = currentStableId - break inner + var loadedCount = 0 + var error = false + for content in contents { + if case .result = content { + loadedCount += 1 + } else if case .none = content { + error = true + } + } + + if error { + self.onError() + } else if loadedCount == contents.count { + self.onReady() + + if !contents.isEmpty && self.currentStickerPacks.isEmpty { + if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne { + scrollToItem = GridNodeScrollToItem(index: 0, position: .top(0.0), transition: .immediate, directionHint: .up, adjustForSection: false) + } + } + + if self.titleNode.attributedText == nil { + if let titlePlaceholderNode = self.titlePlaceholderNode { + self.titlePlaceholderNode = nil + titlePlaceholderNode.removeFromSupernode() } } - let resolvedStableId: Int - if let stableId = stableId { - resolvedStableId = stableId - } else { - resolvedStableId = self.nextStableId - self.nextStableId += 1 - } + self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.EmojiPack_Title, font: titleFont, textColor: self.presentationData.theme.actionSheet.primaryTextColor, paragraphAlignment: .center) + updateLayout = true - self.nextStableId += 1 - entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: nil, isEmpty: false, isPremium: false, isLocked: false)) - } - if self.titlePlaceholderNode == nil { - let titlePlaceholderNode = ShimmerEffectNode() - self.titlePlaceholderNode = titlePlaceholderNode - self.titleContainer.addSubnode(titlePlaceholderNode) - } - case .none: - self.onError() - self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) - self.controller?.dismiss(animated: true, completion: nil) - case let .result(info, items, installed): - self.onReady() - if !items.isEmpty && self.currentStickerPack == nil { - if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne { - scrollToItem = GridNodeScrollToItem(index: 0, position: .top(0.0), transition: .immediate, directionHint: .up, adjustForSection: false) - } - } - - self.currentStickerPack = (info, items, installed) - - if self.titleNode.attributedText == nil { - if let titlePlaceholderNode = self.titlePlaceholderNode { - self.titlePlaceholderNode = nil - titlePlaceholderNode.removeFromSupernode() - } - } - - let titleFont = Font.semibold(17.0) - let entities = generateTextEntities(info.title, enabledTypes: [.mention]) - self.titleNode.attributedText = stringWithAppliedEntities(info.title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont) - - updateLayout = true - - - let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 }) - - var generalItems: [StickerPackItem] = [] - var premiumItems: [StickerPackItem] = [] - - for item in items { - if item.file.isPremiumSticker { - premiumItems.append(item) - } else { - generalItems.append(item) - } - } - - let addItem: (StickerPackItem, Bool, Bool) -> Void = { item, isPremium, isLocked in - var stableId: Int? - inner: for entry in self.currentEntries { - if case let .sticker(_, currentStableId, stickerItem, _, _, _) = entry, let stickerItem = stickerItem, stickerItem.file.fileId == item.file.fileId { - stableId = currentStableId - break inner + var currentStickerPacks: [(StickerPackCollectionInfo, [StickerPackItem], Bool)] = [] + + var index = 0 + var installedCount = 0 + for content in contents { + if case let .result(info, items, isInstalled) = content { + entries.append(.emojis(index: index, stableId: index, info: info, items: items, title: info.title, isInstalled: isInstalled)) + if isInstalled { + installedCount += 1 + } + currentStickerPacks.append((info, items, isInstalled)) } + index += 1 } - let resolvedStableId: Int - if let stableId = stableId { - resolvedStableId = stableId + self.currentStickerPacks = currentStickerPacks + + if installedCount == contents.count { + let text = self.presentationData.strings.StickerPack_RemoveEmojiPacksCount(Int32(contents.count)) + self.buttonNode.setTitle(text, with: Font.regular(17.0), with: self.presentationData.theme.list.itemDestructiveColor, for: .normal) + self.buttonNode.setBackgroundImage(nil, for: []) } else { - resolvedStableId = self.nextStableId - self.nextStableId += 1 - } - entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: item, isEmpty: false, isPremium: isPremium, isLocked: isLocked)) - } - - for item in generalItems { - addItem(item, false, false) - } - - if !premiumConfiguration.isPremiumDisabled { - if !premiumItems.isEmpty { - for item in premiumItems { - addItem(item, true, !hasPremium) - } + let text = self.presentationData.strings.StickerPack_AddEmojiPacksCount(Int32(contents.count - installedCount)) + self.buttonNode.setTitle(text, with: Font.semibold(17.0), with: self.presentationData.theme.list.itemCheckColors.foregroundColor, for: .normal) + let roundedAccentBackground = generateImage(CGSize(width: 22.0, height: 22.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(self.presentationData.theme.list.itemCheckColors.fillColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height))) + })?.stretchableImage(withLeftCapWidth: 11, topCapHeight: 11) + self.buttonNode.setBackgroundImage(roundedAccentBackground, for: []) } } - - if installed { - let text: String - if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { - text = self.presentationData.strings.StickerPack_RemoveStickerCount(Int32(entries.count)) - } else { - text = self.presentationData.strings.StickerPack_RemoveMaskCount(Int32(entries.count)) - } - self.buttonNode.setTitle(text, with: Font.regular(17.0), with: self.presentationData.theme.list.itemDestructiveColor, for: .normal) + } else if let contents = contents.first { + switch contents { + case .fetching: + self.onLoading() + entries = [] + self.buttonNode.setTitle(self.presentationData.strings.Channel_NotificationLoading, with: Font.semibold(17.0), with: self.presentationData.theme.list.itemDisabledTextColor, for: .normal) self.buttonNode.setBackgroundImage(nil, for: []) - } else { - let text: String - if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { - text = self.presentationData.strings.StickerPack_AddStickerCount(Int32(entries.count)) - } else { - text = self.presentationData.strings.StickerPack_AddMaskCount(Int32(entries.count)) + + for _ in 0 ..< 16 { + var stableId: Int? + inner: for entry in self.currentEntries { + if case let .sticker(index, currentStableId, stickerItem, _, _, _) = entry, stickerItem == nil, index == entries.count { + stableId = currentStableId + break inner + } + } + + let resolvedStableId: Int + if let stableId = stableId { + resolvedStableId = stableId + } else { + resolvedStableId = self.nextStableId + self.nextStableId += 1 + } + + self.nextStableId += 1 + entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: nil, isEmpty: false, isPremium: false, isLocked: false)) + } + if self.titlePlaceholderNode == nil { + let titlePlaceholderNode = ShimmerEffectNode() + self.titlePlaceholderNode = titlePlaceholderNode + self.titleContainer.addSubnode(titlePlaceholderNode) + } + case .none: + self.onError() + self.controller?.present(textAlertController(context: self.context, title: nil, text: self.presentationData.strings.StickerPack_ErrorNotFound, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + self.controller?.dismiss(animated: true, completion: nil) + case let .result(info, items, installed): + self.onReady() + if !items.isEmpty && self.currentStickerPack == nil { + if let _ = self.validLayout, abs(self.expandScrollProgress - 1.0) < .ulpOfOne { + scrollToItem = GridNodeScrollToItem(index: 0, position: .top(0.0), transition: .immediate, directionHint: .up, adjustForSection: false) + } + } + + self.currentStickerPack = (info, items, installed) + + if self.titleNode.attributedText == nil { + if let titlePlaceholderNode = self.titlePlaceholderNode { + self.titlePlaceholderNode = nil + titlePlaceholderNode.removeFromSupernode() + } + } + + let entities = generateTextEntities(info.title, enabledTypes: [.mention]) + self.titleNode.attributedText = stringWithAppliedEntities(info.title, entities: entities, baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont, message: nil) + + updateLayout = true + + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + entries.append(.emojis(index: 0, stableId: 0, info: info, items: items, title: nil, isInstalled: nil)) + } else { + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 }) + + var generalItems: [StickerPackItem] = [] + var premiumItems: [StickerPackItem] = [] + + for item in items { + if item.file.isPremiumSticker { + premiumItems.append(item) + } else { + generalItems.append(item) + } + } + + let addItem: (StickerPackItem, Bool, Bool) -> Void = { item, isPremium, isLocked in + var stableId: Int? + inner: for entry in self.currentEntries { + if case let .sticker(_, currentStableId, stickerItem, _, _, _) = entry, let stickerItem = stickerItem, stickerItem.file.fileId == item.file.fileId { + stableId = currentStableId + break inner + } + } + let resolvedStableId: Int + if let stableId = stableId { + resolvedStableId = stableId + } else { + resolvedStableId = self.nextStableId + self.nextStableId += 1 + } + entries.append(.sticker(index: entries.count, stableId: resolvedStableId, stickerItem: item, isEmpty: false, isPremium: isPremium, isLocked: isLocked)) + } + + for item in generalItems { + addItem(item, false, false) + } + + if !premiumConfiguration.isPremiumDisabled { + if !premiumItems.isEmpty { + for item in premiumItems { + addItem(item, true, !hasPremium) + } + } + } + } + + if installed { + let text: String + if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { + text = self.presentationData.strings.StickerPack_RemoveStickerCount(Int32(entries.count)) + } else if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + text = self.presentationData.strings.StickerPack_RemoveEmojiCount(Int32(items.count)) + } else { + text = self.presentationData.strings.StickerPack_RemoveMaskCount(Int32(entries.count)) + } + self.buttonNode.setTitle(text, with: Font.regular(17.0), with: self.presentationData.theme.list.itemDestructiveColor, for: .normal) + self.buttonNode.setBackgroundImage(nil, for: []) + } else { + let text: String + if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks { + text = self.presentationData.strings.StickerPack_AddStickerCount(Int32(entries.count)) + } else if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + text = self.presentationData.strings.StickerPack_AddEmojiCount(Int32(items.count)) + } else { + text = self.presentationData.strings.StickerPack_AddMaskCount(Int32(entries.count)) + } + self.buttonNode.setTitle(text, with: Font.semibold(17.0), with: self.presentationData.theme.list.itemCheckColors.foregroundColor, for: .normal) + let roundedAccentBackground = generateImage(CGSize(width: 22.0, height: 22.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(self.presentationData.theme.list.itemCheckColors.fillColor.cgColor) + context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height))) + })?.stretchableImage(withLeftCapWidth: 11, topCapHeight: 11) + self.buttonNode.setBackgroundImage(roundedAccentBackground, for: []) } - self.buttonNode.setTitle(text, with: Font.semibold(17.0), with: self.presentationData.theme.list.itemCheckColors.foregroundColor, for: .normal) - let roundedAccentBackground = generateImage(CGSize(width: 22.0, height: 22.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(self.presentationData.theme.list.itemCheckColors.fillColor.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height))) - })?.stretchableImage(withLeftCapWidth: 11, topCapHeight: 11) - self.buttonNode.setBackgroundImage(roundedAccentBackground, for: []) } - } let previousEntries = self.currentEntries self.currentEntries = entries @@ -736,19 +915,13 @@ private final class StickerPackContainer: ASDisplayNode { } if updateLayout, let (layout, _, _, _) = self.validLayout { - let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude)) - self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize) - - let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude)) - self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize) - - self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0)) - self.updateLayout(layout: layout, transition: .immediate) } - let transaction = StickerPackPreviewGridTransaction(previousList: previousEntries, list: entries, account: self.context.account, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, scrollToItem: scrollToItem) - self.enqueueTransaction(transaction) + if let controller = self.controller { + let transaction = StickerPackPreviewGridTransaction(previousList: previousEntries, list: entries, context: self.context, interaction: self.interaction, theme: self.presentationData.theme, strings: self.presentationData.strings, animationCache: controller.animationCache, animationRenderer: controller.animationRenderer, scrollToItem: scrollToItem) + self.enqueueTransaction(transaction) + } } var topContentInset: CGFloat { @@ -788,6 +961,19 @@ private final class StickerPackContainer: ASDisplayNode { var buttonHeight: CGFloat = 50.0 var actionAreaTopInset: CGFloat = 8.0 var actionAreaBottomInset: CGFloat = 16.0 + if !self.currentStickerPacks.isEmpty { + var installedCount = 0 + for (_, _, isInstalled) in self.currentStickerPacks { + if isInstalled { + installedCount += 1 + } + } + if installedCount == self.currentStickerPacks.count { + buttonHeight = 42.0 + actionAreaTopInset = 1.0 + actionAreaBottomInset = 2.0 + } + } if let (_, _, isInstalled) = self.currentStickerPack, isInstalled { buttonHeight = 42.0 actionAreaTopInset = 1.0 @@ -813,9 +999,21 @@ private final class StickerPackContainer: ASDisplayNode { let itemWidth = floor(fillingWidth / CGFloat(itemsPerRow)) let gridLeftInset = floor((layout.size.width - fillingWidth) / 2.0) let contentHeight: CGFloat - if let (_, items, _) = self.currentStickerPack { - let rowCount = items.count / itemsPerRow + ((items.count % itemsPerRow) == 0 ? 0 : 1) - contentHeight = itemWidth * CGFloat(rowCount) + if !self.currentStickerPacks.isEmpty { + var packsHeight = 0.0 + for stickerPack in currentStickerPacks { + let layout = ItemLayout(width: fillingWidth, itemsCount: stickerPack.1.count, hasTitle: true) + packsHeight += layout.height + } + contentHeight = packsHeight + 8.0 + } else if let (info, items, _) = self.currentStickerPack { + if info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks { + let layout = ItemLayout(width: fillingWidth, itemsCount: items.count, hasTitle: false) + contentHeight = layout.height + } else { + let rowCount = items.count / itemsPerRow + ((items.count % itemsPerRow) == 0 ? 0 : 1) + contentHeight = itemWidth * CGFloat(rowCount) + } } else { contentHeight = gridFrame.size.height } @@ -848,6 +1046,14 @@ private final class StickerPackContainer: ASDisplayNode { titlePlaceholderNode.updateAbsoluteRect(titlePlaceholderNode.frame.offsetBy(dx: self.titleContainer.frame.minX, dy: self.titleContainer.frame.minY - gridInsets.top - gridFrame.minY), within: gridFrame.size) } + let cancelSize = self.cancelButtonNode.measure(CGSize(width: layout.size.width, height: .greatestFiniteMagnitude)) + self.cancelButtonNode.frame = CGRect(origin: CGPoint(x: layout.safeInsets.left + 16.0, y: 18.0), size: cancelSize) + + let titleSize = self.titleNode.updateLayout(CGSize(width: layout.size.width - cancelSize.width * 2.0 - 40.0, height: .greatestFiniteMagnitude)) + self.titleNode.frame = CGRect(origin: CGPoint(x: floor((-titleSize.width) / 2.0), y: floor((-titleSize.height) / 2.0)), size: titleSize) + + self.moreButtonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - 46.0, y: 5.0), size: CGSize(width: 44.0, height: 44.0)) + if firstTime { while !self.enqueuedTransactions.isEmpty { self.dequeueTransaction() @@ -964,7 +1170,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { private let modalProgressUpdated: (CGFloat, ContainedViewLayoutTransition) -> Void private let dismissed: () -> Void private let presentInGlobalOverlay: (ViewController, Any?) -> Void - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private let openMention: (String) -> Void private let dimNode: ASDisplayNode @@ -986,7 +1192,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { var onReady: () -> Void = {} var onError: () -> Void = {} - init(context: AccountContext, controller: StickerPackScreenImpl, stickerPacks: [StickerPackReference], initialSelectedStickerPackIndex: Int, modalProgressUpdated: @escaping (CGFloat, ContainedViewLayoutTransition) -> Void, dismissed: @escaping () -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, openMention: @escaping (String) -> Void) { + init(context: AccountContext, controller: StickerPackScreenImpl, stickerPacks: [StickerPackReference], initialSelectedStickerPackIndex: Int, modalProgressUpdated: @escaping (CGFloat, ContainedViewLayoutTransition) -> Void, dismissed: @escaping () -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, openMention: @escaping (String) -> Void) { self.context = context self.controller = controller self.presentationData = controller.presentationData @@ -1015,7 +1221,6 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { super.didLoad() self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimNodeTapGesture(_:)))) - self.containerContainingNode.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) } func updatePresentationData(_ presentationData: PresentationData) { @@ -1032,118 +1237,113 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size)) transition.updateFrame(node: self.containerContainingNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - let expandProgress: CGFloat - if self.stickerPacks.count == 1 { - expandProgress = 1.0 - } else { - expandProgress = self.containers[self.selectedStickerPackIndex]?.expandProgress ?? 0.0 - } + let expandProgress: CGFloat = 1.0 + let scaledInset: CGFloat = 12.0 let scaledDistance: CGFloat = 4.0 let minScale = (layout.size.width - scaledInset * 2.0) / layout.size.width let containerScale = expandProgress * 1.0 + (1.0 - expandProgress) * minScale let containerVerticalOffset: CGFloat = (1.0 - expandProgress) * scaledInset * 2.0 + + let i = 0 + let indexOffset = i - self.selectedStickerPackIndex + var scaledOffset: CGFloat = 0.0 + scaledOffset = -CGFloat(indexOffset) * (1.0 - expandProgress) * (scaledInset * 2.0) + CGFloat(indexOffset) * scaledDistance - for i in 0 ..< self.stickerPacks.count { - let indexOffset = i - self.selectedStickerPackIndex - var scaledOffset: CGFloat = 0.0 - scaledOffset = -CGFloat(indexOffset) * (1.0 - expandProgress) * (scaledInset * 2.0) + CGFloat(indexOffset) * scaledDistance - - if abs(indexOffset) <= 1 { - let containerTransition: ContainedViewLayoutTransition - let container: StickerPackContainer - var wasAdded = false - if let current = self.containers[i] { - containerTransition = transition - container = current - } else { - wasAdded = true - containerTransition = .immediate - let index = i - container = StickerPackContainer(index: index, context: context, presentationData: self.presentationData, stickerPack: self.stickerPacks[i], decideNextAction: { [weak self] container, action in - guard let strongSelf = self, let layout = strongSelf.validLayout else { - return .dismiss - } - if index == strongSelf.stickerPacks.count - 1 { - return .dismiss - } else { - switch action { - case .add: - var allAdded = true - for _ in index + 1 ..< strongSelf.stickerPacks.count { - if let container = strongSelf.containers[index], let (_, _, installed) = container.currentStickerPack { - if !installed { - allAdded = false - } - } else { + if abs(indexOffset) <= 1 { + let containerTransition: ContainedViewLayoutTransition + let container: StickerPackContainer + var wasAdded = false + if let current = self.containers[i] { + containerTransition = transition + container = current + } else { + wasAdded = true + containerTransition = .immediate + let index = i + container = StickerPackContainer(index: index, context: context, presentationData: self.presentationData, stickerPacks: self.stickerPacks, decideNextAction: { [weak self] container, action in + guard let strongSelf = self, let layout = strongSelf.validLayout else { + return .dismiss + } + if index == strongSelf.stickerPacks.count - 1 { + return .dismiss + } else { + switch action { + case .add: + var allAdded = true + for _ in index + 1 ..< strongSelf.stickerPacks.count { + if let container = strongSelf.containers[index], let (_, _, installed) = container.currentStickerPack { + if !installed { allAdded = false } - } - if allAdded { - return .dismiss - } - case .remove: - if strongSelf.stickerPacks.count == 1 { - return .dismiss } else { - return .ignored + allAdded = false } } - } - - strongSelf.selectedStickerPackIndex = strongSelf.selectedStickerPackIndex + 1 - strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring)) - return .navigatedNext - }, requestDismiss: { [weak self] in - self?.dismiss() - }, expandProgressUpdated: { [weak self] container, transition, expandTransition in - guard let strongSelf = self, let layout = strongSelf.validLayout else { - return - } - if index == strongSelf.selectedStickerPackIndex, let container = strongSelf.containers[strongSelf.selectedStickerPackIndex] { - let modalProgress = container.modalProgress - strongSelf.modalProgressUpdated(modalProgress, transition) - strongSelf.containerLayoutUpdated(layout, transition: expandTransition) - for (_, otherContainer) in strongSelf.containers { - if otherContainer !== container { - otherContainer.syncExpandProgress(expandScrollProgress: container.expandScrollProgress, expandProgress: container.expandProgress, modalProgress: container.modalProgress, transition: expandTransition) - } + if allAdded { + return .dismiss + } + case .remove: + if strongSelf.stickerPacks.count == 1 { + return .dismiss + } else { + return .ignored } } - }, presentInGlobalOverlay: presentInGlobalOverlay, sendSticker: sendSticker, openMention: openMention, controller: self.controller) - container.onReady = { [weak self] in - self?.onReady() } - container.onLoading = { [weak self] in - self?.onLoading() + + strongSelf.selectedStickerPackIndex = strongSelf.selectedStickerPackIndex + 1 + strongSelf.containerLayoutUpdated(layout, transition: .animated(duration: 0.3, curve: .spring)) + return .navigatedNext + }, requestDismiss: { [weak self] in + self?.dismiss() + }, expandProgressUpdated: { [weak self] container, transition, expandTransition in + guard let strongSelf = self, let layout = strongSelf.validLayout else { + return } - container.onError = { [weak self] in - self?.onError() - } - self.containerContainingNode.addSubnode(container) - self.containers[i] = container - } - - let containerFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * layout.size.width + self.relativeToSelectedStickerPackTransition + scaledOffset, y: containerVerticalOffset), size: layout.size) - containerTransition.updateFrame(node: container, frame: containerFrame, beginWithCurrentState: true) - containerTransition.updateSublayerTransformScaleAndOffset(node: container, scale: containerScale, offset: CGPoint(), beginWithCurrentState: true) - if container.validLayout?.0 != layout { - container.updateLayout(layout: layout, transition: containerTransition) - } - - if wasAdded { - if let selectedContainer = self.containers[self.selectedStickerPackIndex] { - if selectedContainer !== container { - container.syncExpandProgress(expandScrollProgress: selectedContainer.expandScrollProgress, expandProgress: selectedContainer.expandProgress, modalProgress: selectedContainer.modalProgress, transition: .immediate) + if index == strongSelf.selectedStickerPackIndex, let container = strongSelf.containers[strongSelf.selectedStickerPackIndex] { + let modalProgress = container.modalProgress + strongSelf.modalProgressUpdated(modalProgress, transition) + strongSelf.containerLayoutUpdated(layout, transition: expandTransition) + for (_, otherContainer) in strongSelf.containers { + if otherContainer !== container { + otherContainer.syncExpandProgress(expandScrollProgress: container.expandScrollProgress, expandProgress: container.expandProgress, modalProgress: container.modalProgress, transition: expandTransition) + } } } + }, presentInGlobalOverlay: presentInGlobalOverlay, sendSticker: sendSticker, openMention: openMention, controller: self.controller) + container.onReady = { [weak self] in + self?.onReady() } - } else { - if let container = self.containers[i] { - container.removeFromSupernode() - self.containers.removeValue(forKey: i) + container.onLoading = { [weak self] in + self?.onLoading() } + container.onError = { [weak self] in + self?.onError() + } + self.containerContainingNode.addSubnode(container) + self.containers[i] = container + } + + let containerFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * layout.size.width + self.relativeToSelectedStickerPackTransition + scaledOffset, y: containerVerticalOffset), size: layout.size) + containerTransition.updateFrame(node: container, frame: containerFrame, beginWithCurrentState: true) + containerTransition.updateSublayerTransformScaleAndOffset(node: container, scale: containerScale, offset: CGPoint(), beginWithCurrentState: true) + if container.validLayout?.0 != layout { + container.updateLayout(layout: layout, transition: containerTransition) + } + + if wasAdded { + if let selectedContainer = self.containers[self.selectedStickerPackIndex] { + if selectedContainer !== container { + container.syncExpandProgress(expandScrollProgress: selectedContainer.expandScrollProgress, expandProgress: selectedContainer.expandProgress, modalProgress: selectedContainer.modalProgress, transition: .immediate) + } + } + } + } else { + if let container = self.containers[i] { + container.removeFromSupernode() + self.containers.removeValue(forKey: i) } } @@ -1302,14 +1502,14 @@ public final class StickerPackScreenImpl: ViewController { private let stickerPacks: [StickerPackReference] private let initialSelectedStickerPackIndex: Int fileprivate weak var parentNavigationController: NavigationController? - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private var controllerNode: StickerPackScreenNode { return self.displayNode as! StickerPackScreenNode } public var dismissed: (() -> Void)? - public var actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? + public var actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? private let _ready = Promise() override public var ready: Promise { @@ -1319,8 +1519,12 @@ public final class StickerPackScreenImpl: ViewController { private let openMentionDisposable = MetaDisposable() private var alreadyDidAppear: Bool = false + private var animatedIn: Bool = false - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil) { + let animationCache: AnimationCache + let animationRenderer: MultiAnimationRenderer + + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil) { self.context = context self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } self.stickerPacks = stickerPacks @@ -1329,6 +1533,19 @@ public final class StickerPackScreenImpl: ViewController { self.sendSticker = sendSticker self.actionPerformed = actionPerformed + self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + + let animationRenderer: MultiAnimationRenderer + /*if #available(iOS 13.0, *) { + animationRenderer = MultiAnimationMetalRendererImpl() + } else {*/ + animationRenderer = MultiAnimationRendererImpl() + //} + + self.animationRenderer = animationRenderer + super.init(navigationBarPresentationData: nil) self.statusBar.statusBarStyle = .Ignore @@ -1417,13 +1634,16 @@ public final class StickerPackScreenImpl: ViewController { } if strongSelf.alreadyDidAppear { - strongSelf.controllerNode.animateIn() + } else { strongSelf.isReady = true } - self?.controllerNode.isHidden = false - self?.controllerNode.animateIn() + strongSelf.controllerNode.isHidden = false + if !strongSelf.animatedIn { + strongSelf.animatedIn = true + strongSelf.controllerNode.animateIn() + } } } } @@ -1465,6 +1685,7 @@ public final class StickerPackScreenImpl: ViewController { self.alreadyDidAppear = true if self.isReady { + self.animatedIn = true self.controllerNode.animateIn() } } @@ -1482,8 +1703,8 @@ public enum StickerPackScreenPerformedAction { case remove(positionInList: Int) } -public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController { - let stickerPacks = [mainStickerPack] +public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController { + //let stickerPacks = [mainStickerPack] let controller = StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker, actionPerformed: actionPerformed) controller.dismissed = dismissed return controller diff --git a/submodules/StickerPeekUI/BUILD b/submodules/StickerPeekUI/BUILD new file mode 100644 index 0000000000..2772c1830c --- /dev/null +++ b/submodules/StickerPeekUI/BUILD @@ -0,0 +1,36 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "StickerPeekUI", + module_name = "StickerPeekUI", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + "//submodules/Display:Display", + "//submodules/Postbox:Postbox", + "//submodules/TelegramCore:TelegramCore", + "//submodules/TelegramPresentationData:TelegramPresentationData", + "//submodules/AccountContext:AccountContext", + "//submodules/TelegramUIPreferences:TelegramUIPreferences", + "//submodules/StickerResources:StickerResources", + "//submodules/AlertUI:AlertUI", + "//submodules/PresentationDataUtils:PresentationDataUtils", + "//submodules/TextFormat:TextFormat", + "//submodules/ActivityIndicator:ActivityIndicator", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", + "//submodules/ShimmerEffect:ShimmerEffect", + "//submodules/ContextUI:ContextUI", + "//submodules/SolidRoundedButtonNode:SolidRoundedButtonNode", + "//submodules/PremiumUI:PremiumUI", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift b/submodules/StickerPeekUI/Sources/StickerPreviewPeekContent.swift similarity index 94% rename from submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift rename to submodules/StickerPeekUI/Sources/StickerPreviewPeekContent.swift index 96c61efd36..1eeef0f26a 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift +++ b/submodules/StickerPeekUI/Sources/StickerPreviewPeekContent.swift @@ -15,13 +15,13 @@ import AccountContext import AppBundle public enum StickerPreviewPeekItem: Equatable { - case pack(StickerPackItem) + case pack(TelegramMediaFile) case found(FoundStickerItem) public var file: TelegramMediaFile { switch self { - case let .pack(item): - return item.file + case let .pack(file): + return file case let .found(item): return item.file } @@ -101,6 +101,8 @@ public final class StickerPreviewPeekContentNode: ASDisplayNode, PeekControllerC private var containerLayout: (ContainerViewLayout, CGFloat)? + private let _ready = Promise() + init(account: Account, item: StickerPreviewPeekItem) { self.account = account self.item = item @@ -117,6 +119,7 @@ public final class StickerPreviewPeekContentNode: ASDisplayNode, PeekControllerC if item.file.isAnimatedSticker || item.file.isVideoSticker { let animationNode = DefaultAnimatedStickerNodeImpl() + animationNode.overrideVisibility = true self.animationNode = animationNode let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512) @@ -166,12 +169,32 @@ public final class StickerPreviewPeekContentNode: ASDisplayNode, PeekControllerC if let additionalAnimationNode = self.additionalAnimationNode { self.addSubnode(additionalAnimationNode) } + + if let animationNode = self.animationNode { + animationNode.started = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf._ready.set(.single(true)) + } + } else { + self.imageNode.imageUpdated = { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf._ready.set(.single(true)) + } + } } deinit { self.effectDisposable.dispose() } + public func ready() -> Signal { + return self._ready.get() + } + public func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { let boundingSize: CGSize if let _ = self.additionalAnimationNode { diff --git a/submodules/TabBarUI/Sources/TabBarController.swift b/submodules/TabBarUI/Sources/TabBarController.swift index c91d0e70b2..af41c83362 100644 --- a/submodules/TabBarUI/Sources/TabBarController.swift +++ b/submodules/TabBarUI/Sources/TabBarController.swift @@ -197,24 +197,23 @@ open class TabBarControllerImpl: ViewController, TabBarController { return } - if strongSelf.selectedIndex == index { - let timestamp = CACurrentMediaTime() - if strongSelf.debugTapCounter.0 < timestamp - 0.4 { - strongSelf.debugTapCounter.0 = timestamp - strongSelf.debugTapCounter.1 = 0 - } - - if strongSelf.debugTapCounter.0 >= timestamp - 0.4 { - strongSelf.debugTapCounter.0 = timestamp - strongSelf.debugTapCounter.1 += 1 - } - - if strongSelf.debugTapCounter.1 >= 10 { - strongSelf.debugTapCounter.1 = 0 - - strongSelf.controllers[index].tabBarItemDebugTapAction?() - } + let timestamp = CACurrentMediaTime() + if strongSelf.debugTapCounter.0 < timestamp - 0.4 { + strongSelf.debugTapCounter.0 = timestamp + strongSelf.debugTapCounter.1 = 0 } + + if strongSelf.debugTapCounter.0 >= timestamp - 0.4 { + strongSelf.debugTapCounter.0 = timestamp + strongSelf.debugTapCounter.1 += 1 + } + + if strongSelf.debugTapCounter.1 >= 10 { + strongSelf.debugTapCounter.1 = 0 + + strongSelf.controllers[index].tabBarItemDebugTapAction?() + } + if let validLayout = strongSelf.validLayout { var updatedLayout = validLayout diff --git a/submodules/TelegramAnimatedStickerNode/Sources/AnimatedStickerUtils.swift b/submodules/TelegramAnimatedStickerNode/Sources/AnimatedStickerUtils.swift index 11a62ea8da..176236668a 100644 --- a/submodules/TelegramAnimatedStickerNode/Sources/AnimatedStickerUtils.swift +++ b/submodules/TelegramAnimatedStickerNode/Sources/AnimatedStickerUtils.swift @@ -263,7 +263,7 @@ public func cacheVideoStickerFrames(path: String, size: CGSize, cacheKey: String return Signal { subscriber in let cancelled = Atomic(value: false) - let source = SoftwareVideoSource(path: path, hintVP9: true) + let source = SoftwareVideoSource(path: path, hintVP9: true, unpremultiplyAlpha: true) let queue = ThreadPoolQueue(threadPool: softwareVideoWorkers) queue.addTask(ThreadPoolTask({ _ in diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 4f77dde770..1adb4032bc 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -182,6 +182,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[922273905] = { return Api.Document.parse_documentEmpty($0) } dict[297109817] = { return Api.DocumentAttribute.parse_documentAttributeAnimated($0) } dict[-1739392570] = { return Api.DocumentAttribute.parse_documentAttributeAudio($0) } + dict[-48981863] = { return Api.DocumentAttribute.parse_documentAttributeCustomEmoji($0) } dict[358154344] = { return Api.DocumentAttribute.parse_documentAttributeFilename($0) } dict[-1744710921] = { return Api.DocumentAttribute.parse_documentAttributeHasStickers($0) } dict[1815593308] = { return Api.DocumentAttribute.parse_documentAttributeImageSize($0) } @@ -326,6 +327,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-610373422] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyPhoneP2P($0) } dict[1461304012] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyProfilePhoto($0) } dict[1335282456] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyStatusTimestamp($0) } + dict[-1360618136] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyVoiceMessages($0) } dict[407582158] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowAll($0) } dict[-2079962673] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowChatParticipants($0) } dict[218751099] = { return Api.InputPrivacyRule.parse_inputPrivacyValueAllowContacts($0) } @@ -343,10 +345,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-427863538] = { return Api.InputStickerSet.parse_inputStickerSetDice($0) } dict[-4838507] = { return Api.InputStickerSet.parse_inputStickerSetEmpty($0) } dict[-1645763991] = { return Api.InputStickerSet.parse_inputStickerSetID($0) } + dict[-930399486] = { return Api.InputStickerSet.parse_inputStickerSetPremiumGifts($0) } dict[-2044933984] = { return Api.InputStickerSet.parse_inputStickerSetShortName($0) } dict[-6249322] = { return Api.InputStickerSetItem.parse_inputStickerSetItem($0) } dict[70813275] = { return Api.InputStickeredMedia.parse_inputStickeredMediaDocument($0) } dict[1251549527] = { return Api.InputStickeredMedia.parse_inputStickeredMediaPhoto($0) } + dict[1634697192] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($0) } + dict[-1502273946] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumSubscription($0) } dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) } dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) } dict[-1881255857] = { return Api.InputThemeSettings.parse_inputThemeSettings($0) } @@ -411,6 +416,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1230047312] = { return Api.MessageAction.parse_messageActionEmpty($0) } dict[-1834538890] = { return Api.MessageAction.parse_messageActionGameScore($0) } dict[-1730095465] = { return Api.MessageAction.parse_messageActionGeoProximityReached($0) } + dict[-1415514682] = { return Api.MessageAction.parse_messageActionGiftPremium($0) } dict[2047704898] = { return Api.MessageAction.parse_messageActionGroupCall($0) } dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) } dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) } @@ -433,6 +439,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1827637959] = { return Api.MessageEntity.parse_messageEntityBotCommand($0) } dict[1280209983] = { return Api.MessageEntity.parse_messageEntityCashtag($0) } dict[681706865] = { return Api.MessageEntity.parse_messageEntityCode($0) } + dict[-925956616] = { return Api.MessageEntity.parse_messageEntityCustomEmoji($0) } dict[1692693954] = { return Api.MessageEntity.parse_messageEntityEmail($0) } dict[1868782349] = { return Api.MessageEntity.parse_messageEntityHashtag($0) } dict[-2106619040] = { return Api.MessageEntity.parse_messageEntityItalic($0) } @@ -537,6 +544,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[982592842] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow($0) } dict[-732254058] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoUnknown($0) } dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) } + dict[-1996951013] = { return Api.PaymentFormMethod.parse_paymentFormMethod($0) } dict[-1868808300] = { return Api.PaymentRequestedInfo.parse_paymentRequestedInfo($0) } dict[-842892769] = { return Api.PaymentSavedCredentials.parse_paymentSavedCredentialsCard($0) } dict[-1566230754] = { return Api.Peer.parse_peerChannel($0) } @@ -574,6 +582,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-591909213] = { return Api.PollResults.parse_pollResults($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[512535275] = { return Api.PostAddress.parse_postAddress($0) } + dict[1958953753] = { return Api.PremiumGiftOption.parse_premiumGiftOption($0) } dict[1124062251] = { return Api.PrivacyKey.parse_privacyKeyAddedByPhone($0) } dict[1343122938] = { return Api.PrivacyKey.parse_privacyKeyChatInvite($0) } dict[1777096355] = { return Api.PrivacyKey.parse_privacyKeyForwards($0) } @@ -582,6 +591,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[961092808] = { return Api.PrivacyKey.parse_privacyKeyPhoneP2P($0) } dict[-1777000467] = { return Api.PrivacyKey.parse_privacyKeyProfilePhoto($0) } dict[-1137792208] = { return Api.PrivacyKey.parse_privacyKeyStatusTimestamp($0) } + dict[110621716] = { return Api.PrivacyKey.parse_privacyKeyVoiceMessages($0) } dict[1698855810] = { return Api.PrivacyRule.parse_privacyValueAllowAll($0) } dict[1796427406] = { return Api.PrivacyRule.parse_privacyValueAllowChatParticipants($0) } dict[-123988] = { return Api.PrivacyRule.parse_privacyValueAllowContacts($0) } @@ -699,8 +709,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-875679776] = { return Api.StatsPercentValue.parse_statsPercentValue($0) } dict[1202287072] = { return Api.StatsURL.parse_statsURL($0) } dict[313694676] = { return Api.StickerPack.parse_stickerPack($0) } - dict[-673242758] = { return Api.StickerSet.parse_stickerSet($0) } + dict[768691932] = { return Api.StickerSet.parse_stickerSet($0) } dict[1678812626] = { return Api.StickerSetCovered.parse_stickerSetCovered($0) } + dict[451763941] = { return Api.StickerSetCovered.parse_stickerSetFullCovered($0) } dict[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) } dict[-1609668650] = { return Api.Theme.parse_theme($0) } dict[-94849324] = { return Api.ThemeSettings.parse_themeSettings($0) } @@ -796,6 +807,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1767677564] = { return Api.Update.parse_updateReadChannelDiscussionOutbox($0) } dict[-1842450928] = { return Api.Update.parse_updateReadChannelInbox($0) } dict[-1218471511] = { return Api.Update.parse_updateReadChannelOutbox($0) } + dict[-78886548] = { return Api.Update.parse_updateReadFeaturedEmojiStickers($0) } dict[1461528386] = { return Api.Update.parse_updateReadFeaturedStickers($0) } dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) } dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) } @@ -827,7 +839,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) } dict[1073147056] = { return Api.User.parse_user($0) } dict[-742634630] = { return Api.User.parse_userEmpty($0) } - dict[-1938625919] = { return Api.UserFull.parse_userFull($0) } + dict[-994968513] = { return Api.UserFull.parse_userFull($0) } dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) } dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) } dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) } @@ -994,7 +1006,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) } dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) } dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) } - dict[-1340916937] = { return Api.payments.PaymentForm.parse_paymentForm($0) } + dict[-1610250415] = { return Api.payments.PaymentForm.parse_paymentForm($0) } dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) } dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) } dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) } @@ -1321,6 +1333,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.InputStickeredMedia: _1.serialize(buffer, boxed) + case let _1 as Api.InputStorePaymentPurpose: + _1.serialize(buffer, boxed) case let _1 as Api.InputTheme: _1.serialize(buffer, boxed) case let _1 as Api.InputThemeSettings: @@ -1407,6 +1421,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.PaymentCharge: _1.serialize(buffer, boxed) + case let _1 as Api.PaymentFormMethod: + _1.serialize(buffer, boxed) case let _1 as Api.PaymentRequestedInfo: _1.serialize(buffer, boxed) case let _1 as Api.PaymentSavedCredentials: @@ -1445,6 +1461,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.PostAddress: _1.serialize(buffer, boxed) + case let _1 as Api.PremiumGiftOption: + _1.serialize(buffer, boxed) case let _1 as Api.PrivacyKey: _1.serialize(buffer, boxed) case let _1 as Api.PrivacyRule: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index e99bde0f5d..089a3b18e6 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -1,3 +1,391 @@ +public extension Api { + enum InputWebDocument: TypeConstructorDescription { + case inputWebDocument(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputWebDocument(let url, let size, let mimeType, let attributes): + if boxed { + buffer.appendInt32(-1678949555) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt32(size, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(attributes.count)) + for item in attributes { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputWebDocument(let url, let size, let mimeType, let attributes): + return ("inputWebDocument", [("url", String(describing: url)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) + } + } + + public static func parse_inputWebDocument(_ reader: BufferReader) -> InputWebDocument? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: [Api.DocumentAttribute]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.InputWebDocument.inputWebDocument(url: _1!, size: _2!, mimeType: _3!, attributes: _4!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum InputWebFileLocation: TypeConstructorDescription { + case inputWebFileGeoPointLocation(geoPoint: Api.InputGeoPoint, accessHash: Int64, w: Int32, h: Int32, zoom: Int32, scale: Int32) + case inputWebFileLocation(url: String, accessHash: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale): + if boxed { + buffer.appendInt32(-1625153079) + } + geoPoint.serialize(buffer, true) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + serializeInt32(zoom, buffer: buffer, boxed: false) + serializeInt32(scale, buffer: buffer, boxed: false) + break + case .inputWebFileLocation(let url, let accessHash): + if boxed { + buffer.appendInt32(-1036396922) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale): + return ("inputWebFileGeoPointLocation", [("geoPoint", String(describing: geoPoint)), ("accessHash", String(describing: accessHash)), ("w", String(describing: w)), ("h", String(describing: h)), ("zoom", String(describing: zoom)), ("scale", String(describing: scale))]) + case .inputWebFileLocation(let url, let accessHash): + return ("inputWebFileLocation", [("url", String(describing: url)), ("accessHash", String(describing: accessHash))]) + } + } + + public static func parse_inputWebFileGeoPointLocation(_ reader: BufferReader) -> InputWebFileLocation? { + var _1: Api.InputGeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint + } + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.InputWebFileLocation.inputWebFileGeoPointLocation(geoPoint: _1!, accessHash: _2!, w: _3!, h: _4!, zoom: _5!, scale: _6!) + } + else { + return nil + } + } + public static func parse_inputWebFileLocation(_ reader: BufferReader) -> InputWebFileLocation? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.InputWebFileLocation.inputWebFileLocation(url: _1!, accessHash: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum Invoice: TypeConstructorDescription { + case invoice(flags: Int32, currency: String, prices: [Api.LabeledPrice], maxTipAmount: Int64?, suggestedTipAmounts: [Int64]?, recurringTermsUrl: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .invoice(let flags, let currency, let prices, let maxTipAmount, let suggestedTipAmounts, let recurringTermsUrl): + if boxed { + buffer.appendInt32(1048946971) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prices.count)) + for item in prices { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 8) != 0 {serializeInt64(maxTipAmount!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 8) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(suggestedTipAmounts!.count)) + for item in suggestedTipAmounts! { + serializeInt64(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 9) != 0 {serializeString(recurringTermsUrl!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .invoice(let flags, let currency, let prices, let maxTipAmount, let suggestedTipAmounts, let recurringTermsUrl): + return ("invoice", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("prices", String(describing: prices)), ("maxTipAmount", String(describing: maxTipAmount)), ("suggestedTipAmounts", String(describing: suggestedTipAmounts)), ("recurringTermsUrl", String(describing: recurringTermsUrl))]) + } + } + + public static func parse_invoice(_ reader: BufferReader) -> Invoice? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: [Api.LabeledPrice]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LabeledPrice.self) + } + var _4: Int64? + if Int(_1!) & Int(1 << 8) != 0 {_4 = reader.readInt64() } + var _5: [Int64]? + if Int(_1!) & Int(1 << 8) != 0 {if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } } + var _6: String? + if Int(_1!) & Int(1 << 9) != 0 {_6 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 8) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 8) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 9) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Invoice.invoice(flags: _1!, currency: _2!, prices: _3!, maxTipAmount: _4, suggestedTipAmounts: _5, recurringTermsUrl: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum JSONObjectValue: TypeConstructorDescription { + case jsonObjectValue(key: String, value: Api.JSONValue) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .jsonObjectValue(let key, let value): + if boxed { + buffer.appendInt32(-1059185703) + } + serializeString(key, buffer: buffer, boxed: false) + value.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .jsonObjectValue(let key, let value): + return ("jsonObjectValue", [("key", String(describing: key)), ("value", String(describing: value))]) + } + } + + public static func parse_jsonObjectValue(_ reader: BufferReader) -> JSONObjectValue? { + var _1: String? + _1 = parseString(reader) + var _2: Api.JSONValue? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.JSONValue + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.JSONObjectValue.jsonObjectValue(key: _1!, value: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum JSONValue: TypeConstructorDescription { + case jsonArray(value: [Api.JSONValue]) + case jsonBool(value: Api.Bool) + case jsonNull + case jsonNumber(value: Double) + case jsonObject(value: [Api.JSONObjectValue]) + case jsonString(value: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .jsonArray(let value): + if boxed { + buffer.appendInt32(-146520221) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(value.count)) + for item in value { + item.serialize(buffer, true) + } + break + case .jsonBool(let value): + if boxed { + buffer.appendInt32(-952869270) + } + value.serialize(buffer, true) + break + case .jsonNull: + if boxed { + buffer.appendInt32(1064139624) + } + + break + case .jsonNumber(let value): + if boxed { + buffer.appendInt32(736157604) + } + serializeDouble(value, buffer: buffer, boxed: false) + break + case .jsonObject(let value): + if boxed { + buffer.appendInt32(-1715350371) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(value.count)) + for item in value { + item.serialize(buffer, true) + } + break + case .jsonString(let value): + if boxed { + buffer.appendInt32(-1222740358) + } + serializeString(value, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .jsonArray(let value): + return ("jsonArray", [("value", String(describing: value))]) + case .jsonBool(let value): + return ("jsonBool", [("value", String(describing: value))]) + case .jsonNull: + return ("jsonNull", []) + case .jsonNumber(let value): + return ("jsonNumber", [("value", String(describing: value))]) + case .jsonObject(let value): + return ("jsonObject", [("value", String(describing: value))]) + case .jsonString(let value): + return ("jsonString", [("value", String(describing: value))]) + } + } + + public static func parse_jsonArray(_ reader: BufferReader) -> JSONValue? { + var _1: [Api.JSONValue]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONValue.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.JSONValue.jsonArray(value: _1!) + } + else { + return nil + } + } + public static func parse_jsonBool(_ reader: BufferReader) -> JSONValue? { + var _1: Api.Bool? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Bool + } + let _c1 = _1 != nil + if _c1 { + return Api.JSONValue.jsonBool(value: _1!) + } + else { + return nil + } + } + public static func parse_jsonNull(_ reader: BufferReader) -> JSONValue? { + return Api.JSONValue.jsonNull + } + public static func parse_jsonNumber(_ reader: BufferReader) -> JSONValue? { + var _1: Double? + _1 = reader.readDouble() + let _c1 = _1 != nil + if _c1 { + return Api.JSONValue.jsonNumber(value: _1!) + } + else { + return nil + } + } + public static func parse_jsonObject(_ reader: BufferReader) -> JSONValue? { + var _1: [Api.JSONObjectValue]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONObjectValue.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.JSONValue.jsonObject(value: _1!) + } + else { + return nil + } + } + public static func parse_jsonString(_ reader: BufferReader) -> JSONValue? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.JSONValue.jsonString(value: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum KeyboardButton: TypeConstructorDescription { case inputKeyboardButtonUrlAuth(flags: Int32, text: String, fwdText: String?, url: String, bot: Api.InputUser) @@ -708,1023 +1096,3 @@ public extension Api { } } -public extension Api { - enum MaskCoords: TypeConstructorDescription { - case maskCoords(n: Int32, x: Double, y: Double, zoom: Double) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .maskCoords(let n, let x, let y, let zoom): - if boxed { - buffer.appendInt32(-1361650766) - } - serializeInt32(n, buffer: buffer, boxed: false) - serializeDouble(x, buffer: buffer, boxed: false) - serializeDouble(y, buffer: buffer, boxed: false) - serializeDouble(zoom, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .maskCoords(let n, let x, let y, let zoom): - return ("maskCoords", [("n", String(describing: n)), ("x", String(describing: x)), ("y", String(describing: y)), ("zoom", String(describing: zoom))]) - } - } - - public static func parse_maskCoords(_ reader: BufferReader) -> MaskCoords? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Double? - _2 = reader.readDouble() - var _3: Double? - _3 = reader.readDouble() - var _4: Double? - _4 = reader.readDouble() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MaskCoords.maskCoords(n: _1!, x: _2!, y: _3!, zoom: _4!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Message: TypeConstructorDescription { - case message(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?) - case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?) - case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, ttlPeriod: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod): - if boxed { - buffer.appendInt32(940666592) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)} - peerId.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} - if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} - serializeInt32(date, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 9) != 0 {media!.serialize(buffer, true)} - if Int(flags) & Int(1 << 6) != 0 {replyMarkup!.serialize(buffer, true)} - if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(forwards!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 23) != 0 {replies!.serialize(buffer, true)} - if Int(flags) & Int(1 << 15) != 0 {serializeInt32(editDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 16) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 17) != 0 {serializeInt64(groupedId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 20) != 0 {reactions!.serialize(buffer, true)} - if Int(flags) & Int(1 << 22) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(restrictionReason!.count)) - for item in restrictionReason! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - case .messageEmpty(let flags, let id, let peerId): - if boxed { - buffer.appendInt32(-1868117372) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {peerId!.serialize(buffer, true)} - break - case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod): - if boxed { - buffer.appendInt32(721967202) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)} - peerId.serialize(buffer, true) - if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} - serializeInt32(date, buffer: buffer, boxed: false) - action.serialize(buffer, true) - if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod): - return ("message", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("peerId", String(describing: peerId)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("date", String(describing: date)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("views", String(describing: views)), ("forwards", String(describing: forwards)), ("replies", String(describing: replies)), ("editDate", String(describing: editDate)), ("postAuthor", String(describing: postAuthor)), ("groupedId", String(describing: groupedId)), ("reactions", String(describing: reactions)), ("restrictionReason", String(describing: restrictionReason)), ("ttlPeriod", String(describing: ttlPeriod))]) - case .messageEmpty(let flags, let id, let peerId): - return ("messageEmpty", [("flags", String(describing: flags)), ("id", String(describing: id)), ("peerId", String(describing: peerId))]) - case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod): - return ("messageService", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("peerId", String(describing: peerId)), ("replyTo", String(describing: replyTo)), ("date", String(describing: date)), ("action", String(describing: action)), ("ttlPeriod", String(describing: ttlPeriod))]) - } - } - - public static func parse_message(_ reader: BufferReader) -> Message? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.Peer? - if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } } - var _4: Api.Peer? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _5: Api.MessageFwdHeader? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader - } } - var _6: Int64? - if Int(_1!) & Int(1 << 11) != 0 {_6 = reader.readInt64() } - var _7: Api.MessageReplyHeader? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader - } } - var _8: Int32? - _8 = reader.readInt32() - var _9: String? - _9 = parseString(reader) - var _10: Api.MessageMedia? - if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.MessageMedia - } } - var _11: Api.ReplyMarkup? - if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup - } } - var _12: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { - _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - var _13: Int32? - if Int(_1!) & Int(1 << 10) != 0 {_13 = reader.readInt32() } - var _14: Int32? - if Int(_1!) & Int(1 << 10) != 0 {_14 = reader.readInt32() } - var _15: Api.MessageReplies? - if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() { - _15 = Api.parse(reader, signature: signature) as? Api.MessageReplies - } } - var _16: Int32? - if Int(_1!) & Int(1 << 15) != 0 {_16 = reader.readInt32() } - var _17: String? - if Int(_1!) & Int(1 << 16) != 0 {_17 = parseString(reader) } - var _18: Int64? - if Int(_1!) & Int(1 << 17) != 0 {_18 = reader.readInt64() } - var _19: Api.MessageReactions? - if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() { - _19 = Api.parse(reader, signature: signature) as? Api.MessageReactions - } } - var _20: [Api.RestrictionReason]? - if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() { - _20 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) - } } - var _21: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_21 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 11) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = (Int(_1!) & Int(1 << 9) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 6) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 10) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 10) == 0) || _14 != nil - let _c15 = (Int(_1!) & Int(1 << 23) == 0) || _15 != nil - let _c16 = (Int(_1!) & Int(1 << 15) == 0) || _16 != nil - let _c17 = (Int(_1!) & Int(1 << 16) == 0) || _17 != nil - let _c18 = (Int(_1!) & Int(1 << 17) == 0) || _18 != nil - let _c19 = (Int(_1!) & Int(1 << 20) == 0) || _19 != nil - let _c20 = (Int(_1!) & Int(1 << 22) == 0) || _20 != nil - let _c21 = (Int(_1!) & Int(1 << 25) == 0) || _21 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 { - return Api.Message.message(flags: _1!, id: _2!, fromId: _3, peerId: _4!, fwdFrom: _5, viaBotId: _6, replyTo: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, forwards: _14, replies: _15, editDate: _16, postAuthor: _17, groupedId: _18, reactions: _19, restrictionReason: _20, ttlPeriod: _21) - } - else { - return nil - } - } - public static func parse_messageEmpty(_ reader: BufferReader) -> Message? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.Peer? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.Message.messageEmpty(flags: _1!, id: _2!, peerId: _3) - } - else { - return nil - } - } - public static func parse_messageService(_ reader: BufferReader) -> Message? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.Peer? - if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } } - var _4: Api.Peer? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _5: Api.MessageReplyHeader? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader - } } - var _6: Int32? - _6 = reader.readInt32() - var _7: Api.MessageAction? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.MessageAction - } - var _8: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_8 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = (Int(_1!) & Int(1 << 25) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.Message.messageService(flags: _1!, id: _2!, fromId: _3, peerId: _4!, replyTo: _5, date: _6!, action: _7!, ttlPeriod: _8) - } - else { - return nil - } - } - - } -} -public extension Api { - enum MessageAction: TypeConstructorDescription { - case messageActionBotAllowed(domain: String) - case messageActionChannelCreate(title: String) - case messageActionChannelMigrateFrom(title: String, chatId: Int64) - case messageActionChatAddUser(users: [Int64]) - case messageActionChatCreate(title: String, users: [Int64]) - case messageActionChatDeletePhoto - case messageActionChatDeleteUser(userId: Int64) - case messageActionChatEditPhoto(photo: Api.Photo) - case messageActionChatEditTitle(title: String) - case messageActionChatJoinedByLink(inviterId: Int64) - case messageActionChatJoinedByRequest - case messageActionChatMigrateTo(channelId: Int64) - case messageActionContactSignUp - case messageActionCustomAction(message: String) - case messageActionEmpty - case messageActionGameScore(gameId: Int64, score: Int32) - case messageActionGeoProximityReached(fromId: Api.Peer, toId: Api.Peer, distance: Int32) - case messageActionGroupCall(flags: Int32, call: Api.InputGroupCall, duration: Int32?) - case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) - case messageActionHistoryClear - case messageActionInviteToGroupCall(call: Api.InputGroupCall, users: [Int64]) - case messageActionPaymentSent(flags: Int32, currency: String, totalAmount: Int64, invoiceSlug: String?) - case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge) - case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) - case messageActionPinMessage - case messageActionScreenshotTaken - case messageActionSecureValuesSent(types: [Api.SecureValueType]) - case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted) - case messageActionSetChatTheme(emoticon: String) - case messageActionSetMessagesTTL(period: Int32) - case messageActionWebViewDataSent(text: String) - case messageActionWebViewDataSentMe(text: String, data: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageActionBotAllowed(let domain): - if boxed { - buffer.appendInt32(-1410748418) - } - serializeString(domain, buffer: buffer, boxed: false) - break - case .messageActionChannelCreate(let title): - if boxed { - buffer.appendInt32(-1781355374) - } - serializeString(title, buffer: buffer, boxed: false) - break - case .messageActionChannelMigrateFrom(let title, let chatId): - if boxed { - buffer.appendInt32(-365344535) - } - serializeString(title, buffer: buffer, boxed: false) - serializeInt64(chatId, buffer: buffer, boxed: false) - break - case .messageActionChatAddUser(let users): - if boxed { - buffer.appendInt32(365886720) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .messageActionChatCreate(let title, let users): - if boxed { - buffer.appendInt32(-1119368275) - } - serializeString(title, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .messageActionChatDeletePhoto: - if boxed { - buffer.appendInt32(-1780220945) - } - - break - case .messageActionChatDeleteUser(let userId): - if boxed { - buffer.appendInt32(-1539362612) - } - serializeInt64(userId, buffer: buffer, boxed: false) - break - case .messageActionChatEditPhoto(let photo): - if boxed { - buffer.appendInt32(2144015272) - } - photo.serialize(buffer, true) - break - case .messageActionChatEditTitle(let title): - if boxed { - buffer.appendInt32(-1247687078) - } - serializeString(title, buffer: buffer, boxed: false) - break - case .messageActionChatJoinedByLink(let inviterId): - if boxed { - buffer.appendInt32(51520707) - } - serializeInt64(inviterId, buffer: buffer, boxed: false) - break - case .messageActionChatJoinedByRequest: - if boxed { - buffer.appendInt32(-339958837) - } - - break - case .messageActionChatMigrateTo(let channelId): - if boxed { - buffer.appendInt32(-519864430) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - break - case .messageActionContactSignUp: - if boxed { - buffer.appendInt32(-202219658) - } - - break - case .messageActionCustomAction(let message): - if boxed { - buffer.appendInt32(-85549226) - } - serializeString(message, buffer: buffer, boxed: false) - break - case .messageActionEmpty: - if boxed { - buffer.appendInt32(-1230047312) - } - - break - case .messageActionGameScore(let gameId, let score): - if boxed { - buffer.appendInt32(-1834538890) - } - serializeInt64(gameId, buffer: buffer, boxed: false) - serializeInt32(score, buffer: buffer, boxed: false) - break - case .messageActionGeoProximityReached(let fromId, let toId, let distance): - if boxed { - buffer.appendInt32(-1730095465) - } - fromId.serialize(buffer, true) - toId.serialize(buffer, true) - serializeInt32(distance, buffer: buffer, boxed: false) - break - case .messageActionGroupCall(let flags, let call, let duration): - if boxed { - buffer.appendInt32(2047704898) - } - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} - break - case .messageActionGroupCallScheduled(let call, let scheduleDate): - if boxed { - buffer.appendInt32(-1281329567) - } - call.serialize(buffer, true) - serializeInt32(scheduleDate, buffer: buffer, boxed: false) - break - case .messageActionHistoryClear: - if boxed { - buffer.appendInt32(-1615153660) - } - - break - case .messageActionInviteToGroupCall(let call, let users): - if boxed { - buffer.appendInt32(1345295095) - } - call.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug): - if boxed { - buffer.appendInt32(-1776926890) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(totalAmount, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)} - break - case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): - if boxed { - buffer.appendInt32(-1892568281) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(totalAmount, buffer: buffer, boxed: false) - serializeBytes(payload, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} - charge.serialize(buffer, true) - break - case .messageActionPhoneCall(let flags, let callId, let reason, let duration): - if boxed { - buffer.appendInt32(-2132731265) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(callId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} - break - case .messageActionPinMessage: - if boxed { - buffer.appendInt32(-1799538451) - } - - break - case .messageActionScreenshotTaken: - if boxed { - buffer.appendInt32(1200788123) - } - - break - case .messageActionSecureValuesSent(let types): - if boxed { - buffer.appendInt32(-648257196) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(types.count)) - for item in types { - item.serialize(buffer, true) - } - break - case .messageActionSecureValuesSentMe(let values, let credentials): - if boxed { - buffer.appendInt32(455635795) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(values.count)) - for item in values { - item.serialize(buffer, true) - } - credentials.serialize(buffer, true) - break - case .messageActionSetChatTheme(let emoticon): - if boxed { - buffer.appendInt32(-1434950843) - } - serializeString(emoticon, buffer: buffer, boxed: false) - break - case .messageActionSetMessagesTTL(let period): - if boxed { - buffer.appendInt32(-1441072131) - } - serializeInt32(period, buffer: buffer, boxed: false) - break - case .messageActionWebViewDataSent(let text): - if boxed { - buffer.appendInt32(-1262252875) - } - serializeString(text, buffer: buffer, boxed: false) - break - case .messageActionWebViewDataSentMe(let text, let data): - if boxed { - buffer.appendInt32(1205698681) - } - serializeString(text, buffer: buffer, boxed: false) - serializeString(data, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageActionBotAllowed(let domain): - return ("messageActionBotAllowed", [("domain", String(describing: domain))]) - case .messageActionChannelCreate(let title): - return ("messageActionChannelCreate", [("title", String(describing: title))]) - case .messageActionChannelMigrateFrom(let title, let chatId): - return ("messageActionChannelMigrateFrom", [("title", String(describing: title)), ("chatId", String(describing: chatId))]) - case .messageActionChatAddUser(let users): - return ("messageActionChatAddUser", [("users", String(describing: users))]) - case .messageActionChatCreate(let title, let users): - return ("messageActionChatCreate", [("title", String(describing: title)), ("users", String(describing: users))]) - case .messageActionChatDeletePhoto: - return ("messageActionChatDeletePhoto", []) - case .messageActionChatDeleteUser(let userId): - return ("messageActionChatDeleteUser", [("userId", String(describing: userId))]) - case .messageActionChatEditPhoto(let photo): - return ("messageActionChatEditPhoto", [("photo", String(describing: photo))]) - case .messageActionChatEditTitle(let title): - return ("messageActionChatEditTitle", [("title", String(describing: title))]) - case .messageActionChatJoinedByLink(let inviterId): - return ("messageActionChatJoinedByLink", [("inviterId", String(describing: inviterId))]) - case .messageActionChatJoinedByRequest: - return ("messageActionChatJoinedByRequest", []) - case .messageActionChatMigrateTo(let channelId): - return ("messageActionChatMigrateTo", [("channelId", String(describing: channelId))]) - case .messageActionContactSignUp: - return ("messageActionContactSignUp", []) - case .messageActionCustomAction(let message): - return ("messageActionCustomAction", [("message", String(describing: message))]) - case .messageActionEmpty: - return ("messageActionEmpty", []) - case .messageActionGameScore(let gameId, let score): - return ("messageActionGameScore", [("gameId", String(describing: gameId)), ("score", String(describing: score))]) - case .messageActionGeoProximityReached(let fromId, let toId, let distance): - return ("messageActionGeoProximityReached", [("fromId", String(describing: fromId)), ("toId", String(describing: toId)), ("distance", String(describing: distance))]) - case .messageActionGroupCall(let flags, let call, let duration): - return ("messageActionGroupCall", [("flags", String(describing: flags)), ("call", String(describing: call)), ("duration", String(describing: duration))]) - case .messageActionGroupCallScheduled(let call, let scheduleDate): - return ("messageActionGroupCallScheduled", [("call", String(describing: call)), ("scheduleDate", String(describing: scheduleDate))]) - case .messageActionHistoryClear: - return ("messageActionHistoryClear", []) - case .messageActionInviteToGroupCall(let call, let users): - return ("messageActionInviteToGroupCall", [("call", String(describing: call)), ("users", String(describing: users))]) - case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug): - return ("messageActionPaymentSent", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("invoiceSlug", String(describing: invoiceSlug))]) - case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): - return ("messageActionPaymentSentMe", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("payload", String(describing: payload)), ("info", String(describing: info)), ("shippingOptionId", String(describing: shippingOptionId)), ("charge", String(describing: charge))]) - case .messageActionPhoneCall(let flags, let callId, let reason, let duration): - return ("messageActionPhoneCall", [("flags", String(describing: flags)), ("callId", String(describing: callId)), ("reason", String(describing: reason)), ("duration", String(describing: duration))]) - case .messageActionPinMessage: - return ("messageActionPinMessage", []) - case .messageActionScreenshotTaken: - return ("messageActionScreenshotTaken", []) - case .messageActionSecureValuesSent(let types): - return ("messageActionSecureValuesSent", [("types", String(describing: types))]) - case .messageActionSecureValuesSentMe(let values, let credentials): - return ("messageActionSecureValuesSentMe", [("values", String(describing: values)), ("credentials", String(describing: credentials))]) - case .messageActionSetChatTheme(let emoticon): - return ("messageActionSetChatTheme", [("emoticon", String(describing: emoticon))]) - case .messageActionSetMessagesTTL(let period): - return ("messageActionSetMessagesTTL", [("period", String(describing: period))]) - case .messageActionWebViewDataSent(let text): - return ("messageActionWebViewDataSent", [("text", String(describing: text))]) - case .messageActionWebViewDataSentMe(let text, let data): - return ("messageActionWebViewDataSentMe", [("text", String(describing: text)), ("data", String(describing: data))]) - } - } - - public static func parse_messageActionBotAllowed(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionBotAllowed(domain: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChannelCreate(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChannelCreate(title: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChannelMigrateFrom(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionChannelMigrateFrom(title: _1!, chatId: _2!) - } - else { - return nil - } - } - public static func parse_messageActionChatAddUser(_ reader: BufferReader) -> MessageAction? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatAddUser(users: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChatCreate(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - var _2: [Int64]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionChatCreate(title: _1!, users: _2!) - } - else { - return nil - } - } - public static func parse_messageActionChatDeletePhoto(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionChatDeletePhoto - } - public static func parse_messageActionChatDeleteUser(_ reader: BufferReader) -> MessageAction? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatDeleteUser(userId: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChatEditPhoto(_ reader: BufferReader) -> MessageAction? { - var _1: Api.Photo? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Photo - } - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatEditPhoto(photo: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChatEditTitle(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatEditTitle(title: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChatJoinedByLink(_ reader: BufferReader) -> MessageAction? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatJoinedByLink(inviterId: _1!) - } - else { - return nil - } - } - public static func parse_messageActionChatJoinedByRequest(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionChatJoinedByRequest - } - public static func parse_messageActionChatMigrateTo(_ reader: BufferReader) -> MessageAction? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionChatMigrateTo(channelId: _1!) - } - else { - return nil - } - } - public static func parse_messageActionContactSignUp(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionContactSignUp - } - public static func parse_messageActionCustomAction(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionCustomAction(message: _1!) - } - else { - return nil - } - } - public static func parse_messageActionEmpty(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionEmpty - } - public static func parse_messageActionGameScore(_ reader: BufferReader) -> MessageAction? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionGameScore(gameId: _1!, score: _2!) - } - else { - return nil - } - } - public static func parse_messageActionGeoProximityReached(_ reader: BufferReader) -> MessageAction? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Api.Peer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageAction.messageActionGeoProximityReached(fromId: _1!, toId: _2!, distance: _3!) - } - else { - return nil - } - } - public static func parse_messageActionGroupCall(_ reader: BufferReader) -> MessageAction? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.InputGroupCall? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall - } - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageAction.messageActionGroupCall(flags: _1!, call: _2!, duration: _3) - } - else { - return nil - } - } - public static func parse_messageActionGroupCallScheduled(_ reader: BufferReader) -> MessageAction? { - var _1: Api.InputGroupCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionGroupCallScheduled(call: _1!, scheduleDate: _2!) - } - else { - return nil - } - } - public static func parse_messageActionHistoryClear(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionHistoryClear - } - public static func parse_messageActionInviteToGroupCall(_ reader: BufferReader) -> MessageAction? { - var _1: Api.InputGroupCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall - } - var _2: [Int64]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionInviteToGroupCall(call: _1!, users: _2!) - } - else { - return nil - } - } - public static func parse_messageActionPaymentSent(_ reader: BufferReader) -> MessageAction? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MessageAction.messageActionPaymentSent(flags: _1!, currency: _2!, totalAmount: _3!, invoiceSlug: _4) - } - else { - return nil - } - } - public static func parse_messageActionPaymentSentMe(_ reader: BufferReader) -> MessageAction? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Int64? - _3 = reader.readInt64() - var _4: Buffer? - _4 = parseBytes(reader) - var _5: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - var _6: String? - if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } - var _7: Api.PaymentCharge? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.PaymentCharge - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.MessageAction.messageActionPaymentSentMe(flags: _1!, currency: _2!, totalAmount: _3!, payload: _4!, info: _5, shippingOptionId: _6, charge: _7!) - } - else { - return nil - } - } - public static func parse_messageActionPhoneCall(_ reader: BufferReader) -> MessageAction? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.PhoneCallDiscardReason? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.PhoneCallDiscardReason - } } - var _4: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MessageAction.messageActionPhoneCall(flags: _1!, callId: _2!, reason: _3, duration: _4) - } - else { - return nil - } - } - public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionPinMessage - } - public static func parse_messageActionScreenshotTaken(_ reader: BufferReader) -> MessageAction? { - return Api.MessageAction.messageActionScreenshotTaken - } - public static func parse_messageActionSecureValuesSent(_ reader: BufferReader) -> MessageAction? { - var _1: [Api.SecureValueType]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValueType.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionSecureValuesSent(types: _1!) - } - else { - return nil - } - } - public static func parse_messageActionSecureValuesSentMe(_ reader: BufferReader) -> MessageAction? { - var _1: [Api.SecureValue]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) - } - var _2: Api.SecureCredentialsEncrypted? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.SecureCredentialsEncrypted - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionSecureValuesSentMe(values: _1!, credentials: _2!) - } - else { - return nil - } - } - public static func parse_messageActionSetChatTheme(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionSetChatTheme(emoticon: _1!) - } - else { - return nil - } - } - public static func parse_messageActionSetMessagesTTL(_ reader: BufferReader) -> MessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionSetMessagesTTL(period: _1!) - } - else { - return nil - } - } - public static func parse_messageActionWebViewDataSent(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionWebViewDataSent(text: _1!) - } - else { - return nil - } - } - public static func parse_messageActionWebViewDataSentMe(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageAction.messageActionWebViewDataSentMe(text: _1!, data: _2!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 8172159a5c..47642963ed 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1,509 +1,43 @@ public extension Api { - enum MessageEntity: TypeConstructorDescription { - case inputMessageEntityMentionName(offset: Int32, length: Int32, userId: Api.InputUser) - case messageEntityBankCard(offset: Int32, length: Int32) - case messageEntityBlockquote(offset: Int32, length: Int32) - case messageEntityBold(offset: Int32, length: Int32) - case messageEntityBotCommand(offset: Int32, length: Int32) - case messageEntityCashtag(offset: Int32, length: Int32) - case messageEntityCode(offset: Int32, length: Int32) - case messageEntityEmail(offset: Int32, length: Int32) - case messageEntityHashtag(offset: Int32, length: Int32) - case messageEntityItalic(offset: Int32, length: Int32) - case messageEntityMention(offset: Int32, length: Int32) - case messageEntityMentionName(offset: Int32, length: Int32, userId: Int64) - case messageEntityPhone(offset: Int32, length: Int32) - case messageEntityPre(offset: Int32, length: Int32, language: String) - case messageEntitySpoiler(offset: Int32, length: Int32) - case messageEntityStrike(offset: Int32, length: Int32) - case messageEntityTextUrl(offset: Int32, length: Int32, url: String) - case messageEntityUnderline(offset: Int32, length: Int32) - case messageEntityUnknown(offset: Int32, length: Int32) - case messageEntityUrl(offset: Int32, length: Int32) + enum MaskCoords: TypeConstructorDescription { + case maskCoords(n: Int32, x: Double, y: Double, zoom: Double) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .inputMessageEntityMentionName(let offset, let length, let userId): + case .maskCoords(let n, let x, let y, let zoom): if boxed { - buffer.appendInt32(546203849) + buffer.appendInt32(-1361650766) } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - break - case .messageEntityBankCard(let offset, let length): - if boxed { - buffer.appendInt32(1981704948) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityBlockquote(let offset, let length): - if boxed { - buffer.appendInt32(34469328) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityBold(let offset, let length): - if boxed { - buffer.appendInt32(-1117713463) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityBotCommand(let offset, let length): - if boxed { - buffer.appendInt32(1827637959) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityCashtag(let offset, let length): - if boxed { - buffer.appendInt32(1280209983) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityCode(let offset, let length): - if boxed { - buffer.appendInt32(681706865) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityEmail(let offset, let length): - if boxed { - buffer.appendInt32(1692693954) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityHashtag(let offset, let length): - if boxed { - buffer.appendInt32(1868782349) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityItalic(let offset, let length): - if boxed { - buffer.appendInt32(-2106619040) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityMention(let offset, let length): - if boxed { - buffer.appendInt32(-100378723) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityMentionName(let offset, let length, let userId): - if boxed { - buffer.appendInt32(-595914432) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - break - case .messageEntityPhone(let offset, let length): - if boxed { - buffer.appendInt32(-1687559349) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityPre(let offset, let length, let language): - if boxed { - buffer.appendInt32(1938967520) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - serializeString(language, buffer: buffer, boxed: false) - break - case .messageEntitySpoiler(let offset, let length): - if boxed { - buffer.appendInt32(852137487) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityStrike(let offset, let length): - if boxed { - buffer.appendInt32(-1090087980) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityTextUrl(let offset, let length, let url): - if boxed { - buffer.appendInt32(1990644519) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - break - case .messageEntityUnderline(let offset, let length): - if boxed { - buffer.appendInt32(-1672577397) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityUnknown(let offset, let length): - if boxed { - buffer.appendInt32(-1148011883) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .messageEntityUrl(let offset, let length): - if boxed { - buffer.appendInt32(1859134776) - } - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) + serializeInt32(n, buffer: buffer, boxed: false) + serializeDouble(x, buffer: buffer, boxed: false) + serializeDouble(y, buffer: buffer, boxed: false) + serializeDouble(zoom, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .inputMessageEntityMentionName(let offset, let length, let userId): - return ("inputMessageEntityMentionName", [("offset", String(describing: offset)), ("length", String(describing: length)), ("userId", String(describing: userId))]) - case .messageEntityBankCard(let offset, let length): - return ("messageEntityBankCard", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityBlockquote(let offset, let length): - return ("messageEntityBlockquote", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityBold(let offset, let length): - return ("messageEntityBold", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityBotCommand(let offset, let length): - return ("messageEntityBotCommand", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityCashtag(let offset, let length): - return ("messageEntityCashtag", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityCode(let offset, let length): - return ("messageEntityCode", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityEmail(let offset, let length): - return ("messageEntityEmail", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityHashtag(let offset, let length): - return ("messageEntityHashtag", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityItalic(let offset, let length): - return ("messageEntityItalic", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityMention(let offset, let length): - return ("messageEntityMention", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityMentionName(let offset, let length, let userId): - return ("messageEntityMentionName", [("offset", String(describing: offset)), ("length", String(describing: length)), ("userId", String(describing: userId))]) - case .messageEntityPhone(let offset, let length): - return ("messageEntityPhone", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityPre(let offset, let length, let language): - return ("messageEntityPre", [("offset", String(describing: offset)), ("length", String(describing: length)), ("language", String(describing: language))]) - case .messageEntitySpoiler(let offset, let length): - return ("messageEntitySpoiler", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityStrike(let offset, let length): - return ("messageEntityStrike", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityTextUrl(let offset, let length, let url): - return ("messageEntityTextUrl", [("offset", String(describing: offset)), ("length", String(describing: length)), ("url", String(describing: url))]) - case .messageEntityUnderline(let offset, let length): - return ("messageEntityUnderline", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityUnknown(let offset, let length): - return ("messageEntityUnknown", [("offset", String(describing: offset)), ("length", String(describing: length))]) - case .messageEntityUrl(let offset, let length): - return ("messageEntityUrl", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .maskCoords(let n, let x, let y, let zoom): + return ("maskCoords", [("n", String(describing: n)), ("x", String(describing: x)), ("y", String(describing: y)), ("zoom", String(describing: zoom))]) } } - public static func parse_inputMessageEntityMentionName(_ reader: BufferReader) -> MessageEntity? { + public static func parse_maskCoords(_ reader: BufferReader) -> MaskCoords? { var _1: Int32? _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.InputUser? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.InputUser - } + var _2: Double? + _2 = reader.readDouble() + var _3: Double? + _3 = reader.readDouble() + var _4: Double? + _4 = reader.readDouble() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageEntity.inputMessageEntityMentionName(offset: _1!, length: _2!, userId: _3!) - } - else { - return nil - } - } - public static func parse_messageEntityBankCard(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityBankCard(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityBlockquote(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityBlockquote(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityBold(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityBold(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityBotCommand(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityBotCommand(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityCashtag(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityCashtag(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityCode(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityCode(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityEmail(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityEmail(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityHashtag(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityHashtag(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityItalic(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityItalic(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityMention(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityMention(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityMentionName(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageEntity.messageEntityMentionName(offset: _1!, length: _2!, userId: _3!) - } - else { - return nil - } - } - public static func parse_messageEntityPhone(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityPhone(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityPre(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageEntity.messageEntityPre(offset: _1!, length: _2!, language: _3!) - } - else { - return nil - } - } - public static func parse_messageEntitySpoiler(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntitySpoiler(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityStrike(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityStrike(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityTextUrl(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageEntity.messageEntityTextUrl(offset: _1!, length: _2!, url: _3!) - } - else { - return nil - } - } - public static func parse_messageEntityUnderline(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityUnderline(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityUnknown(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityUnknown(offset: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_messageEntityUrl(_ reader: BufferReader) -> MessageEntity? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageEntity.messageEntityUrl(offset: _1!, length: _2!) + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MaskCoords.maskCoords(n: _1!, x: _2!, y: _3!, zoom: _4!) } else { return nil @@ -513,69 +47,227 @@ public extension Api { } } public extension Api { - enum MessageFwdHeader: TypeConstructorDescription { - case messageFwdHeader(flags: Int32, fromId: Api.Peer?, fromName: String?, date: Int32, channelPost: Int32?, postAuthor: String?, savedFromPeer: Api.Peer?, savedFromMsgId: Int32?, psaType: String?) + enum Message: TypeConstructorDescription { + case message(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?) + case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?) + case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, ttlPeriod: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .messageFwdHeader(let flags, let fromId, let fromName, let date, let channelPost, let postAuthor, let savedFromPeer, let savedFromMsgId, let psaType): + case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod): if boxed { - buffer.appendInt32(1601666510) + buffer.appendInt32(940666592) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {fromId!.serialize(buffer, true)} - if Int(flags) & Int(1 << 5) != 0 {serializeString(fromName!, buffer: buffer, boxed: false)} + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)} + peerId.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} + if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} serializeInt32(date, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {savedFromPeer!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(savedFromMsgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 6) != 0 {serializeString(psaType!, buffer: buffer, boxed: false)} + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 9) != 0 {media!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {replyMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(forwards!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 23) != 0 {replies!.serialize(buffer, true)} + if Int(flags) & Int(1 << 15) != 0 {serializeInt32(editDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 16) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 17) != 0 {serializeInt64(groupedId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 20) != 0 {reactions!.serialize(buffer, true)} + if Int(flags) & Int(1 << 22) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(restrictionReason!.count)) + for item in restrictionReason! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} + break + case .messageEmpty(let flags, let id, let peerId): + if boxed { + buffer.appendInt32(-1868117372) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {peerId!.serialize(buffer, true)} + break + case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod): + if boxed { + buffer.appendInt32(721967202) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)} + peerId.serialize(buffer, true) + if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} + serializeInt32(date, buffer: buffer, boxed: false) + action.serialize(buffer, true) + if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .messageFwdHeader(let flags, let fromId, let fromName, let date, let channelPost, let postAuthor, let savedFromPeer, let savedFromMsgId, let psaType): - return ("messageFwdHeader", [("flags", String(describing: flags)), ("fromId", String(describing: fromId)), ("fromName", String(describing: fromName)), ("date", String(describing: date)), ("channelPost", String(describing: channelPost)), ("postAuthor", String(describing: postAuthor)), ("savedFromPeer", String(describing: savedFromPeer)), ("savedFromMsgId", String(describing: savedFromMsgId)), ("psaType", String(describing: psaType))]) + case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod): + return ("message", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("peerId", String(describing: peerId)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("date", String(describing: date)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("views", String(describing: views)), ("forwards", String(describing: forwards)), ("replies", String(describing: replies)), ("editDate", String(describing: editDate)), ("postAuthor", String(describing: postAuthor)), ("groupedId", String(describing: groupedId)), ("reactions", String(describing: reactions)), ("restrictionReason", String(describing: restrictionReason)), ("ttlPeriod", String(describing: ttlPeriod))]) + case .messageEmpty(let flags, let id, let peerId): + return ("messageEmpty", [("flags", String(describing: flags)), ("id", String(describing: id)), ("peerId", String(describing: peerId))]) + case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod): + return ("messageService", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("peerId", String(describing: peerId)), ("replyTo", String(describing: replyTo)), ("date", String(describing: date)), ("action", String(describing: action)), ("ttlPeriod", String(describing: ttlPeriod))]) } } - public static func parse_messageFwdHeader(_ reader: BufferReader) -> MessageFwdHeader? { + public static func parse_message(_ reader: BufferReader) -> Message? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.Peer? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.Peer? + if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer } } - var _3: String? - if Int(_1!) & Int(1 << 5) != 0 {_3 = parseString(reader) } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } - var _6: String? - if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } - var _7: Api.Peer? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.Peer + var _4: Api.Peer? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _5: Api.MessageFwdHeader? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader + } } + var _6: Int64? + if Int(_1!) & Int(1 << 11) != 0 {_6 = reader.readInt64() } + var _7: Api.MessageReplyHeader? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader } } var _8: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } + _8 = reader.readInt32() var _9: String? - if Int(_1!) & Int(1 << 6) != 0 {_9 = parseString(reader) } + _9 = parseString(reader) + var _10: Api.MessageMedia? + if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.MessageMedia + } } + var _11: Api.ReplyMarkup? + if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup + } } + var _12: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { + _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + var _13: Int32? + if Int(_1!) & Int(1 << 10) != 0 {_13 = reader.readInt32() } + var _14: Int32? + if Int(_1!) & Int(1 << 10) != 0 {_14 = reader.readInt32() } + var _15: Api.MessageReplies? + if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() { + _15 = Api.parse(reader, signature: signature) as? Api.MessageReplies + } } + var _16: Int32? + if Int(_1!) & Int(1 << 15) != 0 {_16 = reader.readInt32() } + var _17: String? + if Int(_1!) & Int(1 << 16) != 0 {_17 = parseString(reader) } + var _18: Int64? + if Int(_1!) & Int(1 << 17) != 0 {_18 = reader.readInt64() } + var _19: Api.MessageReactions? + if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() { + _19 = Api.parse(reader, signature: signature) as? Api.MessageReactions + } } + var _20: [Api.RestrictionReason]? + if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() { + _20 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) + } } + var _21: Int32? + if Int(_1!) & Int(1 << 25) != 0 {_21 = reader.readInt32() } let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _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 << 4) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.MessageFwdHeader.messageFwdHeader(flags: _1!, fromId: _2, fromName: _3, date: _4!, channelPost: _5, postAuthor: _6, savedFromPeer: _7, savedFromMsgId: _8, psaType: _9) + let _c6 = (Int(_1!) & Int(1 << 11) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = (Int(_1!) & Int(1 << 9) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 6) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 10) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 10) == 0) || _14 != nil + let _c15 = (Int(_1!) & Int(1 << 23) == 0) || _15 != nil + let _c16 = (Int(_1!) & Int(1 << 15) == 0) || _16 != nil + let _c17 = (Int(_1!) & Int(1 << 16) == 0) || _17 != nil + let _c18 = (Int(_1!) & Int(1 << 17) == 0) || _18 != nil + let _c19 = (Int(_1!) & Int(1 << 20) == 0) || _19 != nil + let _c20 = (Int(_1!) & Int(1 << 22) == 0) || _20 != nil + let _c21 = (Int(_1!) & Int(1 << 25) == 0) || _21 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 { + return Api.Message.message(flags: _1!, id: _2!, fromId: _3, peerId: _4!, fwdFrom: _5, viaBotId: _6, replyTo: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, forwards: _14, replies: _15, editDate: _16, postAuthor: _17, groupedId: _18, reactions: _19, restrictionReason: _20, ttlPeriod: _21) + } + else { + return nil + } + } + public static func parse_messageEmpty(_ reader: BufferReader) -> Message? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.Peer? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Message.messageEmpty(flags: _1!, id: _2!, peerId: _3) + } + else { + return nil + } + } + public static func parse_messageService(_ reader: BufferReader) -> Message? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.Peer? + if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer + } } + var _4: Api.Peer? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _5: Api.MessageReplyHeader? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader + } } + var _6: Int32? + _6 = reader.readInt32() + var _7: Api.MessageAction? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.MessageAction + } + var _8: Int32? + if Int(_1!) & Int(1 << 25) != 0 {_8 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = (Int(_1!) & Int(1 << 25) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.Message.messageService(flags: _1!, id: _2!, fromId: _3, peerId: _4!, replyTo: _5, date: _6!, action: _7!, ttlPeriod: _8) } else { return nil @@ -585,425 +277,767 @@ public extension Api { } } public extension Api { - enum MessageInteractionCounters: TypeConstructorDescription { - case messageInteractionCounters(msgId: Int32, views: Int32, forwards: Int32) + enum MessageAction: TypeConstructorDescription { + case messageActionBotAllowed(domain: String) + case messageActionChannelCreate(title: String) + case messageActionChannelMigrateFrom(title: String, chatId: Int64) + case messageActionChatAddUser(users: [Int64]) + case messageActionChatCreate(title: String, users: [Int64]) + case messageActionChatDeletePhoto + case messageActionChatDeleteUser(userId: Int64) + case messageActionChatEditPhoto(photo: Api.Photo) + case messageActionChatEditTitle(title: String) + case messageActionChatJoinedByLink(inviterId: Int64) + case messageActionChatJoinedByRequest + case messageActionChatMigrateTo(channelId: Int64) + case messageActionContactSignUp + case messageActionCustomAction(message: String) + case messageActionEmpty + case messageActionGameScore(gameId: Int64, score: Int32) + case messageActionGeoProximityReached(fromId: Api.Peer, toId: Api.Peer, distance: Int32) + case messageActionGiftPremium(currency: String, amount: Int64, months: Int32) + case messageActionGroupCall(flags: Int32, call: Api.InputGroupCall, duration: Int32?) + case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) + case messageActionHistoryClear + case messageActionInviteToGroupCall(call: Api.InputGroupCall, users: [Int64]) + case messageActionPaymentSent(flags: Int32, currency: String, totalAmount: Int64, invoiceSlug: String?) + case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge) + case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) + case messageActionPinMessage + case messageActionScreenshotTaken + case messageActionSecureValuesSent(types: [Api.SecureValueType]) + case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted) + case messageActionSetChatTheme(emoticon: String) + case messageActionSetMessagesTTL(period: Int32) + case messageActionWebViewDataSent(text: String) + case messageActionWebViewDataSentMe(text: String, data: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .messageInteractionCounters(let msgId, let views, let forwards): + case .messageActionBotAllowed(let domain): if boxed { - buffer.appendInt32(-1387279939) + buffer.appendInt32(-1410748418) } - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt32(views, buffer: buffer, boxed: false) - serializeInt32(forwards, buffer: buffer, boxed: false) + serializeString(domain, buffer: buffer, boxed: false) + break + case .messageActionChannelCreate(let title): + if boxed { + buffer.appendInt32(-1781355374) + } + serializeString(title, buffer: buffer, boxed: false) + break + case .messageActionChannelMigrateFrom(let title, let chatId): + if boxed { + buffer.appendInt32(-365344535) + } + serializeString(title, buffer: buffer, boxed: false) + serializeInt64(chatId, buffer: buffer, boxed: false) + break + case .messageActionChatAddUser(let users): + if boxed { + buffer.appendInt32(365886720) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .messageActionChatCreate(let title, let users): + if boxed { + buffer.appendInt32(-1119368275) + } + serializeString(title, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .messageActionChatDeletePhoto: + if boxed { + buffer.appendInt32(-1780220945) + } + + break + case .messageActionChatDeleteUser(let userId): + if boxed { + buffer.appendInt32(-1539362612) + } + serializeInt64(userId, buffer: buffer, boxed: false) + break + case .messageActionChatEditPhoto(let photo): + if boxed { + buffer.appendInt32(2144015272) + } + photo.serialize(buffer, true) + break + case .messageActionChatEditTitle(let title): + if boxed { + buffer.appendInt32(-1247687078) + } + serializeString(title, buffer: buffer, boxed: false) + break + case .messageActionChatJoinedByLink(let inviterId): + if boxed { + buffer.appendInt32(51520707) + } + serializeInt64(inviterId, buffer: buffer, boxed: false) + break + case .messageActionChatJoinedByRequest: + if boxed { + buffer.appendInt32(-339958837) + } + + break + case .messageActionChatMigrateTo(let channelId): + if boxed { + buffer.appendInt32(-519864430) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + break + case .messageActionContactSignUp: + if boxed { + buffer.appendInt32(-202219658) + } + + break + case .messageActionCustomAction(let message): + if boxed { + buffer.appendInt32(-85549226) + } + serializeString(message, buffer: buffer, boxed: false) + break + case .messageActionEmpty: + if boxed { + buffer.appendInt32(-1230047312) + } + + break + case .messageActionGameScore(let gameId, let score): + if boxed { + buffer.appendInt32(-1834538890) + } + serializeInt64(gameId, buffer: buffer, boxed: false) + serializeInt32(score, buffer: buffer, boxed: false) + break + case .messageActionGeoProximityReached(let fromId, let toId, let distance): + if boxed { + buffer.appendInt32(-1730095465) + } + fromId.serialize(buffer, true) + toId.serialize(buffer, true) + serializeInt32(distance, buffer: buffer, boxed: false) + break + case .messageActionGiftPremium(let currency, let amount, let months): + if boxed { + buffer.appendInt32(-1415514682) + } + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) + serializeInt32(months, buffer: buffer, boxed: false) + break + case .messageActionGroupCall(let flags, let call, let duration): + if boxed { + buffer.appendInt32(2047704898) + } + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} + break + case .messageActionGroupCallScheduled(let call, let scheduleDate): + if boxed { + buffer.appendInt32(-1281329567) + } + call.serialize(buffer, true) + serializeInt32(scheduleDate, buffer: buffer, boxed: false) + break + case .messageActionHistoryClear: + if boxed { + buffer.appendInt32(-1615153660) + } + + break + case .messageActionInviteToGroupCall(let call, let users): + if boxed { + buffer.appendInt32(1345295095) + } + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug): + if boxed { + buffer.appendInt32(-1776926890) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(totalAmount, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)} + break + case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): + if boxed { + buffer.appendInt32(-1892568281) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(totalAmount, buffer: buffer, boxed: false) + serializeBytes(payload, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} + charge.serialize(buffer, true) + break + case .messageActionPhoneCall(let flags, let callId, let reason, let duration): + if boxed { + buffer.appendInt32(-2132731265) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(callId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} + break + case .messageActionPinMessage: + if boxed { + buffer.appendInt32(-1799538451) + } + + break + case .messageActionScreenshotTaken: + if boxed { + buffer.appendInt32(1200788123) + } + + break + case .messageActionSecureValuesSent(let types): + if boxed { + buffer.appendInt32(-648257196) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(types.count)) + for item in types { + item.serialize(buffer, true) + } + break + case .messageActionSecureValuesSentMe(let values, let credentials): + if boxed { + buffer.appendInt32(455635795) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(values.count)) + for item in values { + item.serialize(buffer, true) + } + credentials.serialize(buffer, true) + break + case .messageActionSetChatTheme(let emoticon): + if boxed { + buffer.appendInt32(-1434950843) + } + serializeString(emoticon, buffer: buffer, boxed: false) + break + case .messageActionSetMessagesTTL(let period): + if boxed { + buffer.appendInt32(-1441072131) + } + serializeInt32(period, buffer: buffer, boxed: false) + break + case .messageActionWebViewDataSent(let text): + if boxed { + buffer.appendInt32(-1262252875) + } + serializeString(text, buffer: buffer, boxed: false) + break + case .messageActionWebViewDataSentMe(let text, let data): + if boxed { + buffer.appendInt32(1205698681) + } + serializeString(text, buffer: buffer, boxed: false) + serializeString(data, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .messageInteractionCounters(let msgId, let views, let forwards): - return ("messageInteractionCounters", [("msgId", String(describing: msgId)), ("views", String(describing: views)), ("forwards", String(describing: forwards))]) + case .messageActionBotAllowed(let domain): + return ("messageActionBotAllowed", [("domain", String(describing: domain))]) + case .messageActionChannelCreate(let title): + return ("messageActionChannelCreate", [("title", String(describing: title))]) + case .messageActionChannelMigrateFrom(let title, let chatId): + return ("messageActionChannelMigrateFrom", [("title", String(describing: title)), ("chatId", String(describing: chatId))]) + case .messageActionChatAddUser(let users): + return ("messageActionChatAddUser", [("users", String(describing: users))]) + case .messageActionChatCreate(let title, let users): + return ("messageActionChatCreate", [("title", String(describing: title)), ("users", String(describing: users))]) + case .messageActionChatDeletePhoto: + return ("messageActionChatDeletePhoto", []) + case .messageActionChatDeleteUser(let userId): + return ("messageActionChatDeleteUser", [("userId", String(describing: userId))]) + case .messageActionChatEditPhoto(let photo): + return ("messageActionChatEditPhoto", [("photo", String(describing: photo))]) + case .messageActionChatEditTitle(let title): + return ("messageActionChatEditTitle", [("title", String(describing: title))]) + case .messageActionChatJoinedByLink(let inviterId): + return ("messageActionChatJoinedByLink", [("inviterId", String(describing: inviterId))]) + case .messageActionChatJoinedByRequest: + return ("messageActionChatJoinedByRequest", []) + case .messageActionChatMigrateTo(let channelId): + return ("messageActionChatMigrateTo", [("channelId", String(describing: channelId))]) + case .messageActionContactSignUp: + return ("messageActionContactSignUp", []) + case .messageActionCustomAction(let message): + return ("messageActionCustomAction", [("message", String(describing: message))]) + case .messageActionEmpty: + return ("messageActionEmpty", []) + case .messageActionGameScore(let gameId, let score): + return ("messageActionGameScore", [("gameId", String(describing: gameId)), ("score", String(describing: score))]) + case .messageActionGeoProximityReached(let fromId, let toId, let distance): + return ("messageActionGeoProximityReached", [("fromId", String(describing: fromId)), ("toId", String(describing: toId)), ("distance", String(describing: distance))]) + case .messageActionGiftPremium(let currency, let amount, let months): + return ("messageActionGiftPremium", [("currency", String(describing: currency)), ("amount", String(describing: amount)), ("months", String(describing: months))]) + case .messageActionGroupCall(let flags, let call, let duration): + return ("messageActionGroupCall", [("flags", String(describing: flags)), ("call", String(describing: call)), ("duration", String(describing: duration))]) + case .messageActionGroupCallScheduled(let call, let scheduleDate): + return ("messageActionGroupCallScheduled", [("call", String(describing: call)), ("scheduleDate", String(describing: scheduleDate))]) + case .messageActionHistoryClear: + return ("messageActionHistoryClear", []) + case .messageActionInviteToGroupCall(let call, let users): + return ("messageActionInviteToGroupCall", [("call", String(describing: call)), ("users", String(describing: users))]) + case .messageActionPaymentSent(let flags, let currency, let totalAmount, let invoiceSlug): + return ("messageActionPaymentSent", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("invoiceSlug", String(describing: invoiceSlug))]) + case .messageActionPaymentSentMe(let flags, let currency, let totalAmount, let payload, let info, let shippingOptionId, let charge): + return ("messageActionPaymentSentMe", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("payload", String(describing: payload)), ("info", String(describing: info)), ("shippingOptionId", String(describing: shippingOptionId)), ("charge", String(describing: charge))]) + case .messageActionPhoneCall(let flags, let callId, let reason, let duration): + return ("messageActionPhoneCall", [("flags", String(describing: flags)), ("callId", String(describing: callId)), ("reason", String(describing: reason)), ("duration", String(describing: duration))]) + case .messageActionPinMessage: + return ("messageActionPinMessage", []) + case .messageActionScreenshotTaken: + return ("messageActionScreenshotTaken", []) + case .messageActionSecureValuesSent(let types): + return ("messageActionSecureValuesSent", [("types", String(describing: types))]) + case .messageActionSecureValuesSentMe(let values, let credentials): + return ("messageActionSecureValuesSentMe", [("values", String(describing: values)), ("credentials", String(describing: credentials))]) + case .messageActionSetChatTheme(let emoticon): + return ("messageActionSetChatTheme", [("emoticon", String(describing: emoticon))]) + case .messageActionSetMessagesTTL(let period): + return ("messageActionSetMessagesTTL", [("period", String(describing: period))]) + case .messageActionWebViewDataSent(let text): + return ("messageActionWebViewDataSent", [("text", String(describing: text))]) + case .messageActionWebViewDataSentMe(let text, let data): + return ("messageActionWebViewDataSentMe", [("text", String(describing: text)), ("data", String(describing: data))]) } } - public static func parse_messageInteractionCounters(_ reader: BufferReader) -> MessageInteractionCounters? { - var _1: Int32? - _1 = reader.readInt32() + public static func parse_messageActionBotAllowed(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionBotAllowed(domain: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChannelCreate(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChannelCreate(title: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChannelMigrateFrom(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionChannelMigrateFrom(title: _1!, chatId: _2!) + } + else { + return nil + } + } + public static func parse_messageActionChatAddUser(_ reader: BufferReader) -> MessageAction? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatAddUser(users: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChatCreate(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + var _2: [Int64]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionChatCreate(title: _1!, users: _2!) + } + else { + return nil + } + } + public static func parse_messageActionChatDeletePhoto(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionChatDeletePhoto + } + public static func parse_messageActionChatDeleteUser(_ reader: BufferReader) -> MessageAction? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatDeleteUser(userId: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChatEditPhoto(_ reader: BufferReader) -> MessageAction? { + var _1: Api.Photo? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Photo + } + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatEditPhoto(photo: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChatEditTitle(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatEditTitle(title: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChatJoinedByLink(_ reader: BufferReader) -> MessageAction? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatJoinedByLink(inviterId: _1!) + } + else { + return nil + } + } + public static func parse_messageActionChatJoinedByRequest(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionChatJoinedByRequest + } + public static func parse_messageActionChatMigrateTo(_ reader: BufferReader) -> MessageAction? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionChatMigrateTo(channelId: _1!) + } + else { + return nil + } + } + public static func parse_messageActionContactSignUp(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionContactSignUp + } + public static func parse_messageActionCustomAction(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionCustomAction(message: _1!) + } + else { + return nil + } + } + public static func parse_messageActionEmpty(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionEmpty + } + public static func parse_messageActionGameScore(_ reader: BufferReader) -> MessageAction? { + var _1: Int64? + _1 = reader.readInt64() var _2: Int32? _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionGameScore(gameId: _1!, score: _2!) + } + else { + return nil + } + } + public static func parse_messageActionGeoProximityReached(_ reader: BufferReader) -> MessageAction? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer + } var _3: Int32? _3 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.MessageInteractionCounters.messageInteractionCounters(msgId: _1!, views: _2!, forwards: _3!) + return Api.MessageAction.messageActionGeoProximityReached(fromId: _1!, toId: _2!, distance: _3!) } else { return nil } } - - } -} -public extension Api { - 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?, ttlSeconds: Int32?) - case messageMediaEmpty - case messageMediaGame(game: Api.Game) - case messageMediaGeo(geo: Api.GeoPoint) - case messageMediaGeoLive(flags: Int32, geo: Api.GeoPoint, heading: Int32?, period: Int32, proximityNotificationRadius: Int32?) - case messageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.WebDocument?, receiptMsgId: Int32?, currency: String, totalAmount: Int64, startParam: String) - case messageMediaPhoto(flags: Int32, photo: Api.Photo?, ttlSeconds: Int32?) - case messageMediaPoll(poll: Api.Poll, results: Api.PollResults) - case messageMediaUnsupported - case messageMediaVenue(geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String) - case messageMediaWebPage(webpage: Api.WebPage) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageMediaContact(let phoneNumber, let firstName, let lastName, let vcard, let userId): - if boxed { - buffer.appendInt32(1882335561) - } - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(firstName, buffer: buffer, boxed: false) - serializeString(lastName, buffer: buffer, boxed: false) - serializeString(vcard, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - break - case .messageMediaDice(let value, let emoticon): - if boxed { - buffer.appendInt32(1065280907) - } - serializeInt32(value, buffer: buffer, boxed: false) - serializeString(emoticon, buffer: buffer, boxed: false) - break - case .messageMediaDocument(let flags, let document, let ttlSeconds): - if boxed { - buffer.appendInt32(-1666158377) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} - break - case .messageMediaEmpty: - if boxed { - buffer.appendInt32(1038967584) - } - - break - case .messageMediaGame(let game): - if boxed { - buffer.appendInt32(-38694904) - } - game.serialize(buffer, true) - break - case .messageMediaGeo(let geo): - if boxed { - buffer.appendInt32(1457575028) - } - geo.serialize(buffer, true) - break - case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius): - if boxed { - buffer.appendInt32(-1186937242) - } - serializeInt32(flags, buffer: buffer, boxed: false) - geo.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)} - serializeInt32(period, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)} - break - case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam): - if boxed { - buffer.appendInt32(-2074799289) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(description, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(receiptMsgId!, buffer: buffer, boxed: false)} - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(totalAmount, buffer: buffer, boxed: false) - serializeString(startParam, buffer: buffer, boxed: false) - break - case .messageMediaPhoto(let flags, let photo, let ttlSeconds): - if boxed { - buffer.appendInt32(1766936791) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} - break - case .messageMediaPoll(let poll, let results): - if boxed { - buffer.appendInt32(1272375192) - } - poll.serialize(buffer, true) - results.serialize(buffer, true) - break - case .messageMediaUnsupported: - if boxed { - buffer.appendInt32(-1618676578) - } - - break - case .messageMediaVenue(let geo, let title, let address, let provider, let venueId, let venueType): - if boxed { - buffer.appendInt32(784356159) - } - geo.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - serializeString(address, buffer: buffer, boxed: false) - serializeString(provider, buffer: buffer, boxed: false) - serializeString(venueId, buffer: buffer, boxed: false) - serializeString(venueType, buffer: buffer, boxed: false) - break - case .messageMediaWebPage(let webpage): - if boxed { - buffer.appendInt32(-1557277184) - } - webpage.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageMediaContact(let phoneNumber, let firstName, let lastName, let vcard, let userId): - return ("messageMediaContact", [("phoneNumber", String(describing: phoneNumber)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("vcard", String(describing: vcard)), ("userId", String(describing: userId))]) - case .messageMediaDice(let value, let emoticon): - return ("messageMediaDice", [("value", String(describing: value)), ("emoticon", String(describing: emoticon))]) - case .messageMediaDocument(let flags, let document, let ttlSeconds): - return ("messageMediaDocument", [("flags", String(describing: flags)), ("document", String(describing: document)), ("ttlSeconds", String(describing: ttlSeconds))]) - case .messageMediaEmpty: - return ("messageMediaEmpty", []) - case .messageMediaGame(let game): - return ("messageMediaGame", [("game", String(describing: game))]) - case .messageMediaGeo(let geo): - return ("messageMediaGeo", [("geo", String(describing: geo))]) - case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius): - return ("messageMediaGeoLive", [("flags", String(describing: flags)), ("geo", String(describing: geo)), ("heading", String(describing: heading)), ("period", String(describing: period)), ("proximityNotificationRadius", String(describing: proximityNotificationRadius))]) - case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam): - return ("messageMediaInvoice", [("flags", String(describing: flags)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("receiptMsgId", String(describing: receiptMsgId)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("startParam", String(describing: startParam))]) - case .messageMediaPhoto(let flags, let photo, let ttlSeconds): - return ("messageMediaPhoto", [("flags", String(describing: flags)), ("photo", String(describing: photo)), ("ttlSeconds", String(describing: ttlSeconds))]) - case .messageMediaPoll(let poll, let results): - return ("messageMediaPoll", [("poll", String(describing: poll)), ("results", String(describing: results))]) - case .messageMediaUnsupported: - return ("messageMediaUnsupported", []) - case .messageMediaVenue(let geo, let title, let address, let provider, let venueId, let venueType): - return ("messageMediaVenue", [("geo", String(describing: geo)), ("title", String(describing: title)), ("address", String(describing: address)), ("provider", String(describing: provider)), ("venueId", String(describing: venueId)), ("venueType", String(describing: venueType))]) - case .messageMediaWebPage(let webpage): - return ("messageMediaWebPage", [("webpage", String(describing: webpage))]) - } - } - - public static func parse_messageMediaContact(_ reader: BufferReader) -> MessageMedia? { + public static func parse_messageActionGiftPremium(_ reader: BufferReader) -> MessageAction? { var _1: String? _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: Int64? - _5 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.MessageMedia.messageMediaContact(phoneNumber: _1!, firstName: _2!, lastName: _3!, vcard: _4!, userId: _5!) - } - else { - return nil - } - } - public static func parse_messageMediaDice(_ reader: BufferReader) -> MessageMedia? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageMedia.messageMediaDice(value: _1!, emoticon: _2!) - } - else { - return nil - } - } - public static func parse_messageMediaDocument(_ reader: BufferReader) -> MessageMedia? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.Document? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Document - } } - var _3: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil if _c1 && _c2 && _c3 { - return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, ttlSeconds: _3) + return Api.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, months: _3!) } else { return nil } } - public static func parse_messageMediaEmpty(_ reader: BufferReader) -> MessageMedia? { - return Api.MessageMedia.messageMediaEmpty - } - public static func parse_messageMediaGame(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.Game? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Game - } - let _c1 = _1 != nil - if _c1 { - return Api.MessageMedia.messageMediaGame(game: _1!) - } - else { - return nil - } - } - public static func parse_messageMediaGeo(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.GeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } - let _c1 = _1 != nil - if _c1 { - return Api.MessageMedia.messageMediaGeo(geo: _1!) - } - else { - return nil - } - } - public static func parse_messageMediaGeoLive(_ reader: BufferReader) -> MessageMedia? { + public static func parse_messageActionGroupCall(_ reader: BufferReader) -> MessageAction? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.GeoPoint? + var _2: Api.InputGroupCall? if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.GeoPoint + _2 = Api.parse(reader, signature: signature) as? Api.InputGroupCall } var _3: Int32? if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.MessageMedia.messageMediaGeoLive(flags: _1!, geo: _2!, heading: _3, period: _4!, proximityNotificationRadius: _5) + if _c1 && _c2 && _c3 { + return Api.MessageAction.messageActionGroupCall(flags: _1!, call: _2!, duration: _3) } else { return nil } } - public static func parse_messageMediaInvoice(_ reader: BufferReader) -> MessageMedia? { + public static func parse_messageActionGroupCallScheduled(_ reader: BufferReader) -> MessageAction? { + var _1: Api.InputGroupCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionGroupCallScheduled(call: _1!, scheduleDate: _2!) + } + else { + return nil + } + } + public static func parse_messageActionHistoryClear(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionHistoryClear + } + public static func parse_messageActionInviteToGroupCall(_ reader: BufferReader) -> MessageAction? { + var _1: Api.InputGroupCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall + } + var _2: [Int64]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionInviteToGroupCall(call: _1!, users: _2!) + } + else { + return nil + } + } + public static func parse_messageActionPaymentSent(_ reader: BufferReader) -> MessageAction? { var _1: Int32? _1 = reader.readInt32() var _2: String? _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: Api.WebDocument? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.WebDocument - } } - var _5: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } - var _6: String? - _6 = parseString(reader) - var _7: Int64? - _7 = reader.readInt64() - var _8: String? - _8 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.MessageMedia.messageMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, receiptMsgId: _5, currency: _6!, totalAmount: _7!, startParam: _8!) + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageAction.messageActionPaymentSent(flags: _1!, currency: _2!, totalAmount: _3!, invoiceSlug: _4) } else { return nil } } - public static func parse_messageMediaPhoto(_ reader: BufferReader) -> MessageMedia? { + public static func parse_messageActionPaymentSentMe(_ reader: BufferReader) -> MessageAction? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.Photo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Photo - } } - var _3: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageMedia.messageMediaPhoto(flags: _1!, photo: _2, ttlSeconds: _3) - } - else { - return nil - } - } - public static func parse_messageMediaPoll(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.Poll? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Poll - } - var _2: Api.PollResults? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PollResults - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageMedia.messageMediaPoll(poll: _1!, results: _2!) - } - else { - return nil - } - } - public static func parse_messageMediaUnsupported(_ reader: BufferReader) -> MessageMedia? { - return Api.MessageMedia.messageMediaUnsupported - } - public static func parse_messageMediaVenue(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.GeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } var _2: String? _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() + var _4: Buffer? + _4 = parseBytes(reader) + var _5: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } var _6: String? - _6 = parseString(reader) + if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } + var _7: Api.PaymentCharge? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.PaymentCharge + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.MessageMedia.messageMediaVenue(geo: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!) + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.MessageAction.messageActionPaymentSentMe(flags: _1!, currency: _2!, totalAmount: _3!, payload: _4!, info: _5, shippingOptionId: _6, charge: _7!) } else { return nil } } - public static func parse_messageMediaWebPage(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.WebPage? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.WebPage + public static func parse_messageActionPhoneCall(_ reader: BufferReader) -> MessageAction? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.PhoneCallDiscardReason? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.PhoneCallDiscardReason + } } + var _4: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageAction.messageActionPhoneCall(flags: _1!, callId: _2!, reason: _3, duration: _4) + } + else { + return nil + } + } + public static func parse_messageActionPinMessage(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionPinMessage + } + public static func parse_messageActionScreenshotTaken(_ reader: BufferReader) -> MessageAction? { + return Api.MessageAction.messageActionScreenshotTaken + } + public static func parse_messageActionSecureValuesSent(_ reader: BufferReader) -> MessageAction? { + var _1: [Api.SecureValueType]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValueType.self) } let _c1 = _1 != nil if _c1 { - return Api.MessageMedia.messageMediaWebPage(webpage: _1!) + return Api.MessageAction.messageActionSecureValuesSent(types: _1!) + } + else { + return nil + } + } + public static func parse_messageActionSecureValuesSentMe(_ reader: BufferReader) -> MessageAction? { + var _1: [Api.SecureValue]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) + } + var _2: Api.SecureCredentialsEncrypted? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.SecureCredentialsEncrypted + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionSecureValuesSentMe(values: _1!, credentials: _2!) + } + else { + return nil + } + } + public static func parse_messageActionSetChatTheme(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionSetChatTheme(emoticon: _1!) + } + else { + return nil + } + } + public static func parse_messageActionSetMessagesTTL(_ reader: BufferReader) -> MessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionSetMessagesTTL(period: _1!) + } + else { + return nil + } + } + public static func parse_messageActionWebViewDataSent(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionWebViewDataSent(text: _1!) + } + else { + return nil + } + } + public static func parse_messageActionWebViewDataSentMe(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageAction.messageActionWebViewDataSentMe(text: _1!, data: _2!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api12.swift b/submodules/TelegramApi/Sources/Api12.swift index af91a1bec8..7668430ca7 100644 --- a/submodules/TelegramApi/Sources/Api12.swift +++ b/submodules/TelegramApi/Sources/Api12.swift @@ -1,73 +1,456 @@ public extension Api { - enum MessagePeerReaction: TypeConstructorDescription { - case messagePeerReaction(flags: Int32, peerId: Api.Peer, reaction: String) + enum MessageEntity: TypeConstructorDescription { + case inputMessageEntityMentionName(offset: Int32, length: Int32, userId: Api.InputUser) + case messageEntityBankCard(offset: Int32, length: Int32) + case messageEntityBlockquote(offset: Int32, length: Int32) + case messageEntityBold(offset: Int32, length: Int32) + case messageEntityBotCommand(offset: Int32, length: Int32) + case messageEntityCashtag(offset: Int32, length: Int32) + case messageEntityCode(offset: Int32, length: Int32) + case messageEntityCustomEmoji(offset: Int32, length: Int32, documentId: Int64) + case messageEntityEmail(offset: Int32, length: Int32) + case messageEntityHashtag(offset: Int32, length: Int32) + case messageEntityItalic(offset: Int32, length: Int32) + case messageEntityMention(offset: Int32, length: Int32) + case messageEntityMentionName(offset: Int32, length: Int32, userId: Int64) + case messageEntityPhone(offset: Int32, length: Int32) + case messageEntityPre(offset: Int32, length: Int32, language: String) + case messageEntitySpoiler(offset: Int32, length: Int32) + case messageEntityStrike(offset: Int32, length: Int32) + case messageEntityTextUrl(offset: Int32, length: Int32, url: String) + case messageEntityUnderline(offset: Int32, length: Int32) + case messageEntityUnknown(offset: Int32, length: Int32) + case messageEntityUrl(offset: Int32, length: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .messagePeerReaction(let flags, let peerId, let reaction): + case .inputMessageEntityMentionName(let offset, let length, let userId): if boxed { - buffer.appendInt32(1370914559) + buffer.appendInt32(546203849) } - serializeInt32(flags, buffer: buffer, boxed: false) - peerId.serialize(buffer, true) - serializeString(reaction, buffer: buffer, boxed: false) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + break + case .messageEntityBankCard(let offset, let length): + if boxed { + buffer.appendInt32(1981704948) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityBlockquote(let offset, let length): + if boxed { + buffer.appendInt32(34469328) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityBold(let offset, let length): + if boxed { + buffer.appendInt32(-1117713463) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityBotCommand(let offset, let length): + if boxed { + buffer.appendInt32(1827637959) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityCashtag(let offset, let length): + if boxed { + buffer.appendInt32(1280209983) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityCode(let offset, let length): + if boxed { + buffer.appendInt32(681706865) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityCustomEmoji(let offset, let length, let documentId): + if boxed { + buffer.appendInt32(-925956616) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + serializeInt64(documentId, buffer: buffer, boxed: false) + break + case .messageEntityEmail(let offset, let length): + if boxed { + buffer.appendInt32(1692693954) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityHashtag(let offset, let length): + if boxed { + buffer.appendInt32(1868782349) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityItalic(let offset, let length): + if boxed { + buffer.appendInt32(-2106619040) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityMention(let offset, let length): + if boxed { + buffer.appendInt32(-100378723) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityMentionName(let offset, let length, let userId): + if boxed { + buffer.appendInt32(-595914432) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + break + case .messageEntityPhone(let offset, let length): + if boxed { + buffer.appendInt32(-1687559349) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityPre(let offset, let length, let language): + if boxed { + buffer.appendInt32(1938967520) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + serializeString(language, buffer: buffer, boxed: false) + break + case .messageEntitySpoiler(let offset, let length): + if boxed { + buffer.appendInt32(852137487) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityStrike(let offset, let length): + if boxed { + buffer.appendInt32(-1090087980) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityTextUrl(let offset, let length, let url): + if boxed { + buffer.appendInt32(1990644519) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + break + case .messageEntityUnderline(let offset, let length): + if boxed { + buffer.appendInt32(-1672577397) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityUnknown(let offset, let length): + if boxed { + buffer.appendInt32(-1148011883) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .messageEntityUrl(let offset, let length): + if boxed { + buffer.appendInt32(1859134776) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .messagePeerReaction(let flags, let peerId, let reaction): - return ("messagePeerReaction", [("flags", String(describing: flags)), ("peerId", String(describing: peerId)), ("reaction", String(describing: reaction))]) + case .inputMessageEntityMentionName(let offset, let length, let userId): + return ("inputMessageEntityMentionName", [("offset", String(describing: offset)), ("length", String(describing: length)), ("userId", String(describing: userId))]) + case .messageEntityBankCard(let offset, let length): + return ("messageEntityBankCard", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityBlockquote(let offset, let length): + return ("messageEntityBlockquote", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityBold(let offset, let length): + return ("messageEntityBold", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityBotCommand(let offset, let length): + return ("messageEntityBotCommand", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityCashtag(let offset, let length): + return ("messageEntityCashtag", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityCode(let offset, let length): + return ("messageEntityCode", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityCustomEmoji(let offset, let length, let documentId): + return ("messageEntityCustomEmoji", [("offset", String(describing: offset)), ("length", String(describing: length)), ("documentId", String(describing: documentId))]) + case .messageEntityEmail(let offset, let length): + return ("messageEntityEmail", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityHashtag(let offset, let length): + return ("messageEntityHashtag", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityItalic(let offset, let length): + return ("messageEntityItalic", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityMention(let offset, let length): + return ("messageEntityMention", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityMentionName(let offset, let length, let userId): + return ("messageEntityMentionName", [("offset", String(describing: offset)), ("length", String(describing: length)), ("userId", String(describing: userId))]) + case .messageEntityPhone(let offset, let length): + return ("messageEntityPhone", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityPre(let offset, let length, let language): + return ("messageEntityPre", [("offset", String(describing: offset)), ("length", String(describing: length)), ("language", String(describing: language))]) + case .messageEntitySpoiler(let offset, let length): + return ("messageEntitySpoiler", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityStrike(let offset, let length): + return ("messageEntityStrike", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityTextUrl(let offset, let length, let url): + return ("messageEntityTextUrl", [("offset", String(describing: offset)), ("length", String(describing: length)), ("url", String(describing: url))]) + case .messageEntityUnderline(let offset, let length): + return ("messageEntityUnderline", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityUnknown(let offset, let length): + return ("messageEntityUnknown", [("offset", String(describing: offset)), ("length", String(describing: length))]) + case .messageEntityUrl(let offset, let length): + return ("messageEntityUrl", [("offset", String(describing: offset)), ("length", String(describing: length))]) } } - public static func parse_messagePeerReaction(_ reader: BufferReader) -> MessagePeerReaction? { + public static func parse_inputMessageEntityMentionName(_ reader: BufferReader) -> MessageEntity? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.Peer? + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.InputUser? if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer + _3 = Api.parse(reader, signature: signature) as? Api.InputUser } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageEntity.inputMessageEntityMentionName(offset: _1!, length: _2!, userId: _3!) + } + else { + return nil + } + } + public static func parse_messageEntityBankCard(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityBankCard(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityBlockquote(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityBlockquote(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityBold(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityBold(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityBotCommand(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityBotCommand(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityCashtag(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityCashtag(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityCode(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityCode(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityCustomEmoji(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageEntity.messageEntityCustomEmoji(offset: _1!, length: _2!, documentId: _3!) + } + else { + return nil + } + } + public static func parse_messageEntityEmail(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityEmail(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityHashtag(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityHashtag(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityItalic(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityItalic(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityMention(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityMention(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityMentionName(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageEntity.messageEntityMentionName(offset: _1!, length: _2!, userId: _3!) + } + else { + return nil + } + } + public static func parse_messageEntityPhone(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityPhone(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityPre(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() var _3: String? _3 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.MessagePeerReaction.messagePeerReaction(flags: _1!, peerId: _2!, reaction: _3!) + return Api.MessageEntity.messageEntityPre(offset: _1!, length: _2!, language: _3!) } else { return nil } } - - } -} -public extension Api { - enum MessageRange: TypeConstructorDescription { - case messageRange(minId: Int32, maxId: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageRange(let minId, let maxId): - if boxed { - buffer.appendInt32(182649427) - } - serializeInt32(minId, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageRange(let minId, let maxId): - return ("messageRange", [("minId", String(describing: minId)), ("maxId", String(describing: maxId))]) - } - } - - public static func parse_messageRange(_ reader: BufferReader) -> MessageRange? { + public static func parse_messageEntitySpoiler(_ reader: BufferReader) -> MessageEntity? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? @@ -75,129 +458,80 @@ public extension Api { let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.MessageRange.messageRange(minId: _1!, maxId: _2!) + return Api.MessageEntity.messageEntitySpoiler(offset: _1!, length: _2!) } else { return nil } } - - } -} -public extension Api { - enum MessageReactions: TypeConstructorDescription { - case messageReactions(flags: Int32, results: [Api.ReactionCount], recentReactions: [Api.MessagePeerReaction]?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageReactions(let flags, let results, let recentReactions): - if boxed { - buffer.appendInt32(1328256121) - } - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(results.count)) - for item in results { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(recentReactions!.count)) - for item in recentReactions! { - item.serialize(buffer, true) - }} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageReactions(let flags, let results, let recentReactions): - return ("messageReactions", [("flags", String(describing: flags)), ("results", String(describing: results)), ("recentReactions", String(describing: recentReactions))]) - } - } - - public static func parse_messageReactions(_ reader: BufferReader) -> MessageReactions? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.ReactionCount]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ReactionCount.self) - } - var _3: [Api.MessagePeerReaction]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessagePeerReaction.self) - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageReactions.messageReactions(flags: _1!, results: _2!, recentReactions: _3) - } - else { - return nil - } - } - - } -} -public extension Api { - enum MessageReplies: TypeConstructorDescription { - case messageReplies(flags: Int32, replies: Int32, repliesPts: Int32, recentRepliers: [Api.Peer]?, channelId: Int64?, maxId: Int32?, readMaxId: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageReplies(let flags, let replies, let repliesPts, let recentRepliers, let channelId, let maxId, let readMaxId): - if boxed { - buffer.appendInt32(-2083123262) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(replies, buffer: buffer, boxed: false) - serializeInt32(repliesPts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(recentRepliers!.count)) - for item in recentRepliers! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 0) != 0 {serializeInt64(channelId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(readMaxId!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageReplies(let flags, let replies, let repliesPts, let recentRepliers, let channelId, let maxId, let readMaxId): - return ("messageReplies", [("flags", String(describing: flags)), ("replies", String(describing: replies)), ("repliesPts", String(describing: repliesPts)), ("recentRepliers", String(describing: recentRepliers)), ("channelId", String(describing: channelId)), ("maxId", String(describing: maxId)), ("readMaxId", String(describing: readMaxId))]) - } - } - - public static func parse_messageReplies(_ reader: BufferReader) -> MessageReplies? { + public static func parse_messageEntityStrike(_ reader: BufferReader) -> MessageEntity? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: [Api.Peer]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) - } } - var _5: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } - var _6: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() } - var _7: Int32? - if Int(_1!) & Int(1 << 3) != 0 {_7 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityStrike(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityTextUrl(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.MessageReplies.messageReplies(flags: _1!, replies: _2!, repliesPts: _3!, recentRepliers: _4, channelId: _5, maxId: _6, readMaxId: _7) + if _c1 && _c2 && _c3 { + return Api.MessageEntity.messageEntityTextUrl(offset: _1!, length: _2!, url: _3!) + } + else { + return nil + } + } + public static func parse_messageEntityUnderline(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityUnderline(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityUnknown(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityUnknown(offset: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_messageEntityUrl(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageEntity.messageEntityUrl(offset: _1!, length: _2!) } else { return nil @@ -207,199 +541,69 @@ public extension Api { } } public extension Api { - enum MessageReplyHeader: TypeConstructorDescription { - case messageReplyHeader(flags: Int32, replyToMsgId: Int32, replyToPeerId: Api.Peer?, replyToTopId: Int32?) + enum MessageFwdHeader: TypeConstructorDescription { + case messageFwdHeader(flags: Int32, fromId: Api.Peer?, fromName: String?, date: Int32, channelPost: Int32?, postAuthor: String?, savedFromPeer: Api.Peer?, savedFromMsgId: Int32?, psaType: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .messageReplyHeader(let flags, let replyToMsgId, let replyToPeerId, let replyToTopId): + case .messageFwdHeader(let flags, let fromId, let fromName, let date, let channelPost, let postAuthor, let savedFromPeer, let savedFromMsgId, let psaType): if boxed { - buffer.appendInt32(-1495959709) + buffer.appendInt32(1601666510) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(replyToMsgId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {replyToPeerId!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(replyToTopId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {fromId!.serialize(buffer, true)} + if Int(flags) & Int(1 << 5) != 0 {serializeString(fromName!, buffer: buffer, boxed: false)} + serializeInt32(date, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {savedFromPeer!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(savedFromMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 6) != 0 {serializeString(psaType!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .messageReplyHeader(let flags, let replyToMsgId, let replyToPeerId, let replyToTopId): - return ("messageReplyHeader", [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("replyToPeerId", String(describing: replyToPeerId)), ("replyToTopId", String(describing: replyToTopId))]) + case .messageFwdHeader(let flags, let fromId, let fromName, let date, let channelPost, let postAuthor, let savedFromPeer, let savedFromMsgId, let psaType): + return ("messageFwdHeader", [("flags", String(describing: flags)), ("fromId", String(describing: fromId)), ("fromName", String(describing: fromName)), ("date", String(describing: date)), ("channelPost", String(describing: channelPost)), ("postAuthor", String(describing: postAuthor)), ("savedFromPeer", String(describing: savedFromPeer)), ("savedFromMsgId", String(describing: savedFromMsgId)), ("psaType", String(describing: psaType))]) } } - public static func parse_messageReplyHeader(_ reader: BufferReader) -> MessageReplyHeader? { + public static func parse_messageFwdHeader(_ reader: BufferReader) -> MessageFwdHeader? { var _1: Int32? _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.Peer? + var _2: Api.Peer? if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer + _2 = Api.parse(reader, signature: signature) as? Api.Peer } } + var _3: String? + if Int(_1!) & Int(1 << 5) != 0 {_3 = parseString(reader) } var _4: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MessageReplyHeader.messageReplyHeader(flags: _1!, replyToMsgId: _2!, replyToPeerId: _3, replyToTopId: _4) - } - else { - return nil - } - } - - } -} -public extension Api { - enum MessageUserVote: TypeConstructorDescription { - case messageUserVote(userId: Int64, option: Buffer, date: Int32) - case messageUserVoteInputOption(userId: Int64, date: Int32) - case messageUserVoteMultiple(userId: Int64, options: [Buffer], date: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageUserVote(let userId, let option, let date): - if boxed { - buffer.appendInt32(886196148) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeBytes(option, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .messageUserVoteInputOption(let userId, let date): - if boxed { - buffer.appendInt32(1017491692) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .messageUserVoteMultiple(let userId, let options, let date): - if boxed { - buffer.appendInt32(-1973033641) - } - serializeInt64(userId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(options.count)) - for item in options { - serializeBytes(item, buffer: buffer, boxed: false) - } - serializeInt32(date, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageUserVote(let userId, let option, let date): - return ("messageUserVote", [("userId", String(describing: userId)), ("option", String(describing: option)), ("date", String(describing: date))]) - case .messageUserVoteInputOption(let userId, let date): - return ("messageUserVoteInputOption", [("userId", String(describing: userId)), ("date", String(describing: date))]) - case .messageUserVoteMultiple(let userId, let options, let date): - return ("messageUserVoteMultiple", [("userId", String(describing: userId)), ("options", String(describing: options)), ("date", String(describing: date))]) - } - } - - public static func parse_messageUserVote(_ reader: BufferReader) -> MessageUserVote? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageUserVote.messageUserVote(userId: _1!, option: _2!, date: _3!) - } - else { - return nil - } - } - public static func parse_messageUserVoteInputOption(_ reader: BufferReader) -> MessageUserVote? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.MessageUserVote.messageUserVoteInputOption(userId: _1!, date: _2!) - } - else { - return nil - } - } - public static func parse_messageUserVoteMultiple(_ reader: BufferReader) -> MessageUserVote? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Buffer]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) - } - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.MessageUserVote.messageUserVoteMultiple(userId: _1!, options: _2!, date: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum MessageViews: TypeConstructorDescription { - case messageViews(flags: Int32, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageViews(let flags, let views, let forwards, let replies): - if boxed { - buffer.appendInt32(1163625789) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(forwards!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {replies!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageViews(let flags, let views, let forwards, let replies): - return ("messageViews", [("flags", String(describing: flags)), ("views", String(describing: views)), ("forwards", String(describing: forwards)), ("replies", String(describing: replies))]) - } - } - - public static func parse_messageViews(_ reader: BufferReader) -> MessageViews? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - var _4: Api.MessageReplies? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.MessageReplies + _4 = reader.readInt32() + var _5: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } + var _6: String? + if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } + var _7: Api.Peer? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.Peer } } + var _8: Int32? + if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } + var _9: String? + if Int(_1!) & Int(1 << 6) != 0 {_9 = parseString(reader) } let _c1 = _1 != nil let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MessageViews.messageViews(flags: _1!, views: _2, forwards: _3, replies: _4) + let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _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 << 4) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.MessageFwdHeader.messageFwdHeader(flags: _1!, fromId: _2, fromName: _3, date: _4!, channelPost: _5, postAuthor: _6, savedFromPeer: _7, savedFromMsgId: _8, psaType: _9) } else { return nil @@ -409,260 +613,32 @@ public extension Api { } } public extension Api { - enum MessagesFilter: TypeConstructorDescription { - case inputMessagesFilterChatPhotos - case inputMessagesFilterContacts - case inputMessagesFilterDocument - case inputMessagesFilterEmpty - case inputMessagesFilterGeo - case inputMessagesFilterGif - case inputMessagesFilterMusic - case inputMessagesFilterMyMentions - case inputMessagesFilterPhoneCalls(flags: Int32) - case inputMessagesFilterPhotoVideo - case inputMessagesFilterPhotos - case inputMessagesFilterPinned - case inputMessagesFilterRoundVideo - case inputMessagesFilterRoundVoice - case inputMessagesFilterUrl - case inputMessagesFilterVideo - case inputMessagesFilterVoice + enum MessageInteractionCounters: TypeConstructorDescription { + case messageInteractionCounters(msgId: Int32, views: Int32, forwards: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .inputMessagesFilterChatPhotos: + case .messageInteractionCounters(let msgId, let views, let forwards): if boxed { - buffer.appendInt32(975236280) + buffer.appendInt32(-1387279939) } - - break - case .inputMessagesFilterContacts: - if boxed { - buffer.appendInt32(-530392189) - } - - break - case .inputMessagesFilterDocument: - if boxed { - buffer.appendInt32(-1629621880) - } - - break - case .inputMessagesFilterEmpty: - if boxed { - buffer.appendInt32(1474492012) - } - - break - case .inputMessagesFilterGeo: - if boxed { - buffer.appendInt32(-419271411) - } - - break - case .inputMessagesFilterGif: - if boxed { - buffer.appendInt32(-3644025) - } - - break - case .inputMessagesFilterMusic: - if boxed { - buffer.appendInt32(928101534) - } - - break - case .inputMessagesFilterMyMentions: - if boxed { - buffer.appendInt32(-1040652646) - } - - break - case .inputMessagesFilterPhoneCalls(let flags): - if boxed { - buffer.appendInt32(-2134272152) - } - serializeInt32(flags, buffer: buffer, boxed: false) - break - case .inputMessagesFilterPhotoVideo: - if boxed { - buffer.appendInt32(1458172132) - } - - break - case .inputMessagesFilterPhotos: - if boxed { - buffer.appendInt32(-1777752804) - } - - break - case .inputMessagesFilterPinned: - if boxed { - buffer.appendInt32(464520273) - } - - break - case .inputMessagesFilterRoundVideo: - if boxed { - buffer.appendInt32(-1253451181) - } - - break - case .inputMessagesFilterRoundVoice: - if boxed { - buffer.appendInt32(2054952868) - } - - break - case .inputMessagesFilterUrl: - if boxed { - buffer.appendInt32(2129714567) - } - - break - case .inputMessagesFilterVideo: - if boxed { - buffer.appendInt32(-1614803355) - } - - break - case .inputMessagesFilterVoice: - if boxed { - buffer.appendInt32(1358283666) - } - + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt32(views, buffer: buffer, boxed: false) + serializeInt32(forwards, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .inputMessagesFilterChatPhotos: - return ("inputMessagesFilterChatPhotos", []) - case .inputMessagesFilterContacts: - return ("inputMessagesFilterContacts", []) - case .inputMessagesFilterDocument: - return ("inputMessagesFilterDocument", []) - case .inputMessagesFilterEmpty: - return ("inputMessagesFilterEmpty", []) - case .inputMessagesFilterGeo: - return ("inputMessagesFilterGeo", []) - case .inputMessagesFilterGif: - return ("inputMessagesFilterGif", []) - case .inputMessagesFilterMusic: - return ("inputMessagesFilterMusic", []) - case .inputMessagesFilterMyMentions: - return ("inputMessagesFilterMyMentions", []) - case .inputMessagesFilterPhoneCalls(let flags): - return ("inputMessagesFilterPhoneCalls", [("flags", String(describing: flags))]) - case .inputMessagesFilterPhotoVideo: - return ("inputMessagesFilterPhotoVideo", []) - case .inputMessagesFilterPhotos: - return ("inputMessagesFilterPhotos", []) - case .inputMessagesFilterPinned: - return ("inputMessagesFilterPinned", []) - case .inputMessagesFilterRoundVideo: - return ("inputMessagesFilterRoundVideo", []) - case .inputMessagesFilterRoundVoice: - return ("inputMessagesFilterRoundVoice", []) - case .inputMessagesFilterUrl: - return ("inputMessagesFilterUrl", []) - case .inputMessagesFilterVideo: - return ("inputMessagesFilterVideo", []) - case .inputMessagesFilterVoice: - return ("inputMessagesFilterVoice", []) + case .messageInteractionCounters(let msgId, let views, let forwards): + return ("messageInteractionCounters", [("msgId", String(describing: msgId)), ("views", String(describing: views)), ("forwards", String(describing: forwards))]) } } - public static func parse_inputMessagesFilterChatPhotos(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterChatPhotos - } - public static func parse_inputMessagesFilterContacts(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterContacts - } - public static func parse_inputMessagesFilterDocument(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterDocument - } - public static func parse_inputMessagesFilterEmpty(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterEmpty - } - public static func parse_inputMessagesFilterGeo(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterGeo - } - public static func parse_inputMessagesFilterGif(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterGif - } - public static func parse_inputMessagesFilterMusic(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterMusic - } - public static func parse_inputMessagesFilterMyMentions(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterMyMentions - } - public static func parse_inputMessagesFilterPhoneCalls(_ reader: BufferReader) -> MessagesFilter? { + public static func parse_messageInteractionCounters(_ reader: BufferReader) -> MessageInteractionCounters? { var _1: Int32? _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.MessagesFilter.inputMessagesFilterPhoneCalls(flags: _1!) - } - else { - return nil - } - } - public static func parse_inputMessagesFilterPhotoVideo(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterPhotoVideo - } - public static func parse_inputMessagesFilterPhotos(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterPhotos - } - public static func parse_inputMessagesFilterPinned(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterPinned - } - public static func parse_inputMessagesFilterRoundVideo(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterRoundVideo - } - public static func parse_inputMessagesFilterRoundVoice(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterRoundVoice - } - public static func parse_inputMessagesFilterUrl(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterUrl - } - public static func parse_inputMessagesFilterVideo(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterVideo - } - public static func parse_inputMessagesFilterVoice(_ reader: BufferReader) -> MessagesFilter? { - return Api.MessagesFilter.inputMessagesFilterVoice - } - - } -} -public extension Api { - enum NearestDc: TypeConstructorDescription { - case nearestDc(country: String, thisDc: Int32, nearestDc: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .nearestDc(let country, let thisDc, let nearestDc): - if boxed { - buffer.appendInt32(-1910892683) - } - serializeString(country, buffer: buffer, boxed: false) - serializeInt32(thisDc, buffer: buffer, boxed: false) - serializeInt32(nearestDc, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .nearestDc(let country, let thisDc, let nearestDc): - return ("nearestDc", [("country", String(describing: country)), ("thisDc", String(describing: thisDc)), ("nearestDc", String(describing: nearestDc))]) - } - } - - public static func parse_nearestDc(_ reader: BufferReader) -> NearestDc? { - var _1: String? - _1 = parseString(reader) var _2: Int32? _2 = reader.readInt32() var _3: Int32? @@ -671,7 +647,7 @@ public extension Api { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.NearestDc.nearestDc(country: _1!, thisDc: _2!, nearestDc: _3!) + return Api.MessageInteractionCounters.messageInteractionCounters(msgId: _1!, views: _2!, forwards: _3!) } else { return nil @@ -681,159 +657,385 @@ public extension Api { } } public extension Api { - enum NotificationSound: TypeConstructorDescription { - case notificationSoundDefault - case notificationSoundLocal(title: String, data: String) - case notificationSoundNone - case notificationSoundRingtone(id: Int64) + 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?, ttlSeconds: Int32?) + case messageMediaEmpty + case messageMediaGame(game: Api.Game) + case messageMediaGeo(geo: Api.GeoPoint) + case messageMediaGeoLive(flags: Int32, geo: Api.GeoPoint, heading: Int32?, period: Int32, proximityNotificationRadius: Int32?) + case messageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.WebDocument?, receiptMsgId: Int32?, currency: String, totalAmount: Int64, startParam: String) + case messageMediaPhoto(flags: Int32, photo: Api.Photo?, ttlSeconds: Int32?) + case messageMediaPoll(poll: Api.Poll, results: Api.PollResults) + case messageMediaUnsupported + case messageMediaVenue(geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String) + case messageMediaWebPage(webpage: Api.WebPage) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .notificationSoundDefault: + case .messageMediaContact(let phoneNumber, let firstName, let lastName, let vcard, let userId): if boxed { - buffer.appendInt32(-1746354498) + buffer.appendInt32(1882335561) + } + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(firstName, buffer: buffer, boxed: false) + serializeString(lastName, buffer: buffer, boxed: false) + serializeString(vcard, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + break + case .messageMediaDice(let value, let emoticon): + if boxed { + buffer.appendInt32(1065280907) + } + serializeInt32(value, buffer: buffer, boxed: false) + serializeString(emoticon, buffer: buffer, boxed: false) + break + case .messageMediaDocument(let flags, let document, let ttlSeconds): + if boxed { + buffer.appendInt32(-1666158377) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} + break + case .messageMediaEmpty: + if boxed { + buffer.appendInt32(1038967584) } break - case .notificationSoundLocal(let title, let data): + case .messageMediaGame(let game): if boxed { - buffer.appendInt32(-2096391452) + buffer.appendInt32(-38694904) } + game.serialize(buffer, true) + break + case .messageMediaGeo(let geo): + if boxed { + buffer.appendInt32(1457575028) + } + geo.serialize(buffer, true) + break + case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius): + if boxed { + buffer.appendInt32(-1186937242) + } + serializeInt32(flags, buffer: buffer, boxed: false) + geo.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)} + serializeInt32(period, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)} + break + case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam): + if boxed { + buffer.appendInt32(-2074799289) + } + serializeInt32(flags, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false) - serializeString(data, buffer: buffer, boxed: false) + serializeString(description, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(receiptMsgId!, buffer: buffer, boxed: false)} + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(totalAmount, buffer: buffer, boxed: false) + serializeString(startParam, buffer: buffer, boxed: false) break - case .notificationSoundNone: + case .messageMediaPhoto(let flags, let photo, let ttlSeconds): if boxed { - buffer.appendInt32(1863070943) + buffer.appendInt32(1766936791) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} + break + case .messageMediaPoll(let poll, let results): + if boxed { + buffer.appendInt32(1272375192) + } + poll.serialize(buffer, true) + results.serialize(buffer, true) + break + case .messageMediaUnsupported: + if boxed { + buffer.appendInt32(-1618676578) } break - case .notificationSoundRingtone(let id): + case .messageMediaVenue(let geo, let title, let address, let provider, let venueId, let venueType): if boxed { - buffer.appendInt32(-9666487) + buffer.appendInt32(784356159) } - serializeInt64(id, buffer: buffer, boxed: false) + geo.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + serializeString(address, buffer: buffer, boxed: false) + serializeString(provider, buffer: buffer, boxed: false) + serializeString(venueId, buffer: buffer, boxed: false) + serializeString(venueType, buffer: buffer, boxed: false) + break + case .messageMediaWebPage(let webpage): + if boxed { + buffer.appendInt32(-1557277184) + } + webpage.serialize(buffer, true) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .notificationSoundDefault: - return ("notificationSoundDefault", []) - case .notificationSoundLocal(let title, let data): - return ("notificationSoundLocal", [("title", String(describing: title)), ("data", String(describing: data))]) - case .notificationSoundNone: - return ("notificationSoundNone", []) - case .notificationSoundRingtone(let id): - return ("notificationSoundRingtone", [("id", String(describing: id))]) + case .messageMediaContact(let phoneNumber, let firstName, let lastName, let vcard, let userId): + return ("messageMediaContact", [("phoneNumber", String(describing: phoneNumber)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("vcard", String(describing: vcard)), ("userId", String(describing: userId))]) + case .messageMediaDice(let value, let emoticon): + return ("messageMediaDice", [("value", String(describing: value)), ("emoticon", String(describing: emoticon))]) + case .messageMediaDocument(let flags, let document, let ttlSeconds): + return ("messageMediaDocument", [("flags", String(describing: flags)), ("document", String(describing: document)), ("ttlSeconds", String(describing: ttlSeconds))]) + case .messageMediaEmpty: + return ("messageMediaEmpty", []) + case .messageMediaGame(let game): + return ("messageMediaGame", [("game", String(describing: game))]) + case .messageMediaGeo(let geo): + return ("messageMediaGeo", [("geo", String(describing: geo))]) + case .messageMediaGeoLive(let flags, let geo, let heading, let period, let proximityNotificationRadius): + return ("messageMediaGeoLive", [("flags", String(describing: flags)), ("geo", String(describing: geo)), ("heading", String(describing: heading)), ("period", String(describing: period)), ("proximityNotificationRadius", String(describing: proximityNotificationRadius))]) + case .messageMediaInvoice(let flags, let title, let description, let photo, let receiptMsgId, let currency, let totalAmount, let startParam): + return ("messageMediaInvoice", [("flags", String(describing: flags)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("receiptMsgId", String(describing: receiptMsgId)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("startParam", String(describing: startParam))]) + case .messageMediaPhoto(let flags, let photo, let ttlSeconds): + return ("messageMediaPhoto", [("flags", String(describing: flags)), ("photo", String(describing: photo)), ("ttlSeconds", String(describing: ttlSeconds))]) + case .messageMediaPoll(let poll, let results): + return ("messageMediaPoll", [("poll", String(describing: poll)), ("results", String(describing: results))]) + case .messageMediaUnsupported: + return ("messageMediaUnsupported", []) + case .messageMediaVenue(let geo, let title, let address, let provider, let venueId, let venueType): + return ("messageMediaVenue", [("geo", String(describing: geo)), ("title", String(describing: title)), ("address", String(describing: address)), ("provider", String(describing: provider)), ("venueId", String(describing: venueId)), ("venueType", String(describing: venueType))]) + case .messageMediaWebPage(let webpage): + return ("messageMediaWebPage", [("webpage", String(describing: webpage))]) } } - public static func parse_notificationSoundDefault(_ reader: BufferReader) -> NotificationSound? { - return Api.NotificationSound.notificationSoundDefault - } - public static func parse_notificationSoundLocal(_ reader: BufferReader) -> NotificationSound? { + public static func parse_messageMediaContact(_ reader: BufferReader) -> MessageMedia? { var _1: String? _1 = parseString(reader) var _2: String? _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Int64? + _5 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.MessageMedia.messageMediaContact(phoneNumber: _1!, firstName: _2!, lastName: _3!, vcard: _4!, userId: _5!) + } + else { + return nil + } + } + public static func parse_messageMediaDice(_ reader: BufferReader) -> MessageMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.NotificationSound.notificationSoundLocal(title: _1!, data: _2!) + return Api.MessageMedia.messageMediaDice(value: _1!, emoticon: _2!) } else { return nil } } - public static func parse_notificationSoundNone(_ reader: BufferReader) -> NotificationSound? { - return Api.NotificationSound.notificationSoundNone - } - public static func parse_notificationSoundRingtone(_ reader: BufferReader) -> NotificationSound? { - var _1: Int64? - _1 = reader.readInt64() + public static func parse_messageMediaDocument(_ reader: BufferReader) -> MessageMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Document? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Document + } } + var _3: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } let _c1 = _1 != nil - if _c1 { - return Api.NotificationSound.notificationSoundRingtone(id: _1!) + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageMedia.messageMediaDocument(flags: _1!, document: _2, ttlSeconds: _3) } else { return nil } } - - } -} -public extension Api { - enum NotifyPeer: TypeConstructorDescription { - case notifyBroadcasts - case notifyChats - case notifyPeer(peer: Api.Peer) - case notifyUsers - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .notifyBroadcasts: - if boxed { - buffer.appendInt32(-703403793) - } - - break - case .notifyChats: - if boxed { - buffer.appendInt32(-1073230141) - } - - break - case .notifyPeer(let peer): - if boxed { - buffer.appendInt32(-1613493288) - } - peer.serialize(buffer, true) - break - case .notifyUsers: - if boxed { - buffer.appendInt32(-1261946036) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .notifyBroadcasts: - return ("notifyBroadcasts", []) - case .notifyChats: - return ("notifyChats", []) - case .notifyPeer(let peer): - return ("notifyPeer", [("peer", String(describing: peer))]) - case .notifyUsers: - return ("notifyUsers", []) - } - } - - public static func parse_notifyBroadcasts(_ reader: BufferReader) -> NotifyPeer? { - return Api.NotifyPeer.notifyBroadcasts + public static func parse_messageMediaEmpty(_ reader: BufferReader) -> MessageMedia? { + return Api.MessageMedia.messageMediaEmpty } - public static func parse_notifyChats(_ reader: BufferReader) -> NotifyPeer? { - return Api.NotifyPeer.notifyChats - } - public static func parse_notifyPeer(_ reader: BufferReader) -> NotifyPeer? { - var _1: Api.Peer? + public static func parse_messageMediaGame(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.Game? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer + _1 = Api.parse(reader, signature: signature) as? Api.Game } let _c1 = _1 != nil if _c1 { - return Api.NotifyPeer.notifyPeer(peer: _1!) + return Api.MessageMedia.messageMediaGame(game: _1!) } else { return nil } } - public static func parse_notifyUsers(_ reader: BufferReader) -> NotifyPeer? { - return Api.NotifyPeer.notifyUsers + public static func parse_messageMediaGeo(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.GeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + let _c1 = _1 != nil + if _c1 { + return Api.MessageMedia.messageMediaGeo(geo: _1!) + } + else { + return nil + } + } + public static func parse_messageMediaGeoLive(_ reader: BufferReader) -> MessageMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.GeoPoint? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.MessageMedia.messageMediaGeoLive(flags: _1!, geo: _2!, heading: _3, period: _4!, proximityNotificationRadius: _5) + } + else { + return nil + } + } + public static func parse_messageMediaInvoice(_ reader: BufferReader) -> MessageMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: Api.WebDocument? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.WebDocument + } } + var _5: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } + var _6: String? + _6 = parseString(reader) + var _7: Int64? + _7 = reader.readInt64() + var _8: String? + _8 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.MessageMedia.messageMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, receiptMsgId: _5, currency: _6!, totalAmount: _7!, startParam: _8!) + } + else { + return nil + } + } + public static func parse_messageMediaPhoto(_ reader: BufferReader) -> MessageMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Photo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Photo + } } + var _3: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageMedia.messageMediaPhoto(flags: _1!, photo: _2, ttlSeconds: _3) + } + else { + return nil + } + } + public static func parse_messageMediaPoll(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.Poll? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Poll + } + var _2: Api.PollResults? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PollResults + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageMedia.messageMediaPoll(poll: _1!, results: _2!) + } + else { + return nil + } + } + public static func parse_messageMediaUnsupported(_ reader: BufferReader) -> MessageMedia? { + return Api.MessageMedia.messageMediaUnsupported + } + public static func parse_messageMediaVenue(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.GeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: String? + _6 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.MessageMedia.messageMediaVenue(geo: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!) + } + else { + return nil + } + } + public static func parse_messageMediaWebPage(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.WebPage? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.WebPage + } + let _c1 = _1 != nil + if _c1 { + return Api.MessageMedia.messageMediaWebPage(webpage: _1!) + } + else { + return nil + } } } diff --git a/submodules/TelegramApi/Sources/Api13.swift b/submodules/TelegramApi/Sources/Api13.swift index 4a985aec2a..af91a1bec8 100644 --- a/submodules/TelegramApi/Sources/Api13.swift +++ b/submodules/TelegramApi/Sources/Api13.swift @@ -1,69 +1,41 @@ public extension Api { - enum Page: TypeConstructorDescription { - case page(flags: Int32, url: String, blocks: [Api.PageBlock], photos: [Api.Photo], documents: [Api.Document], views: Int32?) + enum MessagePeerReaction: TypeConstructorDescription { + case messagePeerReaction(flags: Int32, peerId: Api.Peer, reaction: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .page(let flags, let url, let blocks, let photos, let documents, let views): + case .messagePeerReaction(let flags, let peerId, let reaction): if boxed { - buffer.appendInt32(-1738178803) + buffer.appendInt32(1370914559) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocks.count)) - for item in blocks { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(photos.count)) - for item in photos { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(documents.count)) - for item in documents { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} + peerId.serialize(buffer, true) + serializeString(reaction, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .page(let flags, let url, let blocks, let photos, let documents, let views): - return ("page", [("flags", String(describing: flags)), ("url", String(describing: url)), ("blocks", String(describing: blocks)), ("photos", String(describing: photos)), ("documents", String(describing: documents)), ("views", String(describing: views))]) + case .messagePeerReaction(let flags, let peerId, let reaction): + return ("messagePeerReaction", [("flags", String(describing: flags)), ("peerId", String(describing: peerId)), ("reaction", String(describing: reaction))]) } } - public static func parse_page(_ reader: BufferReader) -> Page? { + public static func parse_messagePeerReaction(_ reader: BufferReader) -> MessagePeerReaction? { var _1: Int32? _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: [Api.PageBlock]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer } - var _4: [Api.Photo]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) - } - var _5: [Api.Document]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - var _6: Int32? - if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() } + var _3: String? + _3 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Page.page(flags: _1!, url: _2!, blocks: _3!, photos: _4!, documents: _5!, views: _6) + if _c1 && _c2 && _c3 { + return Api.MessagePeerReaction.messagePeerReaction(flags: _1!, peerId: _2!, reaction: _3!) } else { return nil @@ -73,815 +45,717 @@ public extension Api { } } public extension Api { - indirect enum PageBlock: TypeConstructorDescription { - case pageBlockAnchor(name: String) - case pageBlockAudio(audioId: Int64, caption: Api.PageCaption) - case pageBlockAuthorDate(author: Api.RichText, publishedDate: Int32) - case pageBlockBlockquote(text: Api.RichText, caption: Api.RichText) - case pageBlockChannel(channel: Api.Chat) - case pageBlockCollage(items: [Api.PageBlock], caption: Api.PageCaption) - case pageBlockCover(cover: Api.PageBlock) - case pageBlockDetails(flags: Int32, blocks: [Api.PageBlock], title: Api.RichText) - case pageBlockDivider - case pageBlockEmbed(flags: Int32, url: String?, html: String?, posterPhotoId: Int64?, w: Int32?, h: Int32?, caption: Api.PageCaption) - case pageBlockEmbedPost(url: String, webpageId: Int64, authorPhotoId: Int64, author: String, date: Int32, blocks: [Api.PageBlock], caption: Api.PageCaption) - case pageBlockFooter(text: Api.RichText) - case pageBlockHeader(text: Api.RichText) - case pageBlockKicker(text: Api.RichText) - case pageBlockList(items: [Api.PageListItem]) - case pageBlockMap(geo: Api.GeoPoint, zoom: Int32, w: Int32, h: Int32, caption: Api.PageCaption) - case pageBlockOrderedList(items: [Api.PageListOrderedItem]) - case pageBlockParagraph(text: Api.RichText) - case pageBlockPhoto(flags: Int32, photoId: Int64, caption: Api.PageCaption, url: String?, webpageId: Int64?) - case pageBlockPreformatted(text: Api.RichText, language: String) - case pageBlockPullquote(text: Api.RichText, caption: Api.RichText) - case pageBlockRelatedArticles(title: Api.RichText, articles: [Api.PageRelatedArticle]) - case pageBlockSlideshow(items: [Api.PageBlock], caption: Api.PageCaption) - case pageBlockSubheader(text: Api.RichText) - case pageBlockSubtitle(text: Api.RichText) - case pageBlockTable(flags: Int32, title: Api.RichText, rows: [Api.PageTableRow]) - case pageBlockTitle(text: Api.RichText) - case pageBlockUnsupported - case pageBlockVideo(flags: Int32, videoId: Int64, caption: Api.PageCaption) + enum MessageRange: TypeConstructorDescription { + case messageRange(minId: Int32, maxId: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .pageBlockAnchor(let name): + case .messageRange(let minId, let maxId): if boxed { - buffer.appendInt32(-837994576) + buffer.appendInt32(182649427) } - serializeString(name, buffer: buffer, boxed: false) - break - case .pageBlockAudio(let audioId, let caption): - if boxed { - buffer.appendInt32(-2143067670) - } - serializeInt64(audioId, buffer: buffer, boxed: false) - caption.serialize(buffer, true) - break - case .pageBlockAuthorDate(let author, let publishedDate): - if boxed { - buffer.appendInt32(-1162877472) - } - author.serialize(buffer, true) - serializeInt32(publishedDate, buffer: buffer, boxed: false) - break - case .pageBlockBlockquote(let text, let caption): - if boxed { - buffer.appendInt32(641563686) - } - text.serialize(buffer, true) - caption.serialize(buffer, true) - break - case .pageBlockChannel(let channel): - if boxed { - buffer.appendInt32(-283684427) - } - channel.serialize(buffer, true) - break - case .pageBlockCollage(let items, let caption): - if boxed { - buffer.appendInt32(1705048653) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(items.count)) - for item in items { - item.serialize(buffer, true) - } - caption.serialize(buffer, true) - break - case .pageBlockCover(let cover): - if boxed { - buffer.appendInt32(972174080) - } - cover.serialize(buffer, true) - break - case .pageBlockDetails(let flags, let blocks, let title): - if boxed { - buffer.appendInt32(1987480557) - } - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocks.count)) - for item in blocks { - item.serialize(buffer, true) - } - title.serialize(buffer, true) - break - case .pageBlockDivider: - if boxed { - buffer.appendInt32(-618614392) - } - - break - case .pageBlockEmbed(let flags, let url, let html, let posterPhotoId, let w, let h, let caption): - if boxed { - buffer.appendInt32(-1468953147) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(html!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt64(posterPhotoId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {serializeInt32(w!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {serializeInt32(h!, buffer: buffer, boxed: false)} - caption.serialize(buffer, true) - break - case .pageBlockEmbedPost(let url, let webpageId, let authorPhotoId, let author, let date, let blocks, let caption): - if boxed { - buffer.appendInt32(-229005301) - } - serializeString(url, buffer: buffer, boxed: false) - serializeInt64(webpageId, buffer: buffer, boxed: false) - serializeInt64(authorPhotoId, buffer: buffer, boxed: false) - serializeString(author, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocks.count)) - for item in blocks { - item.serialize(buffer, true) - } - caption.serialize(buffer, true) - break - case .pageBlockFooter(let text): - if boxed { - buffer.appendInt32(1216809369) - } - text.serialize(buffer, true) - break - case .pageBlockHeader(let text): - if boxed { - buffer.appendInt32(-1076861716) - } - text.serialize(buffer, true) - break - case .pageBlockKicker(let text): - if boxed { - buffer.appendInt32(504660880) - } - text.serialize(buffer, true) - break - case .pageBlockList(let items): - if boxed { - buffer.appendInt32(-454524911) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(items.count)) - for item in items { - item.serialize(buffer, true) - } - break - case .pageBlockMap(let geo, let zoom, let w, let h, let caption): - if boxed { - buffer.appendInt32(-1538310410) - } - geo.serialize(buffer, true) - serializeInt32(zoom, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) - caption.serialize(buffer, true) - break - case .pageBlockOrderedList(let items): - if boxed { - buffer.appendInt32(-1702174239) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(items.count)) - for item in items { - item.serialize(buffer, true) - } - break - case .pageBlockParagraph(let text): - if boxed { - buffer.appendInt32(1182402406) - } - text.serialize(buffer, true) - break - case .pageBlockPhoto(let flags, let photoId, let caption, let url, let webpageId): - if boxed { - buffer.appendInt32(391759200) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(photoId, buffer: buffer, boxed: false) - caption.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt64(webpageId!, buffer: buffer, boxed: false)} - break - case .pageBlockPreformatted(let text, let language): - if boxed { - buffer.appendInt32(-1066346178) - } - text.serialize(buffer, true) - serializeString(language, buffer: buffer, boxed: false) - break - case .pageBlockPullquote(let text, let caption): - if boxed { - buffer.appendInt32(1329878739) - } - text.serialize(buffer, true) - caption.serialize(buffer, true) - break - case .pageBlockRelatedArticles(let title, let articles): - if boxed { - buffer.appendInt32(370236054) - } - title.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(articles.count)) - for item in articles { - item.serialize(buffer, true) - } - break - case .pageBlockSlideshow(let items, let caption): - if boxed { - buffer.appendInt32(52401552) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(items.count)) - for item in items { - item.serialize(buffer, true) - } - caption.serialize(buffer, true) - break - case .pageBlockSubheader(let text): - if boxed { - buffer.appendInt32(-248793375) - } - text.serialize(buffer, true) - break - case .pageBlockSubtitle(let text): - if boxed { - buffer.appendInt32(-1879401953) - } - text.serialize(buffer, true) - break - case .pageBlockTable(let flags, let title, let rows): - if boxed { - buffer.appendInt32(-1085412734) - } - serializeInt32(flags, buffer: buffer, boxed: false) - title.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rows.count)) - for item in rows { - item.serialize(buffer, true) - } - break - case .pageBlockTitle(let text): - if boxed { - buffer.appendInt32(1890305021) - } - text.serialize(buffer, true) - break - case .pageBlockUnsupported: - if boxed { - buffer.appendInt32(324435594) - } - - break - case .pageBlockVideo(let flags, let videoId, let caption): - if boxed { - buffer.appendInt32(2089805750) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(videoId, buffer: buffer, boxed: false) - caption.serialize(buffer, true) + serializeInt32(minId, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .pageBlockAnchor(let name): - return ("pageBlockAnchor", [("name", String(describing: name))]) - case .pageBlockAudio(let audioId, let caption): - return ("pageBlockAudio", [("audioId", String(describing: audioId)), ("caption", String(describing: caption))]) - case .pageBlockAuthorDate(let author, let publishedDate): - return ("pageBlockAuthorDate", [("author", String(describing: author)), ("publishedDate", String(describing: publishedDate))]) - case .pageBlockBlockquote(let text, let caption): - return ("pageBlockBlockquote", [("text", String(describing: text)), ("caption", String(describing: caption))]) - case .pageBlockChannel(let channel): - return ("pageBlockChannel", [("channel", String(describing: channel))]) - case .pageBlockCollage(let items, let caption): - return ("pageBlockCollage", [("items", String(describing: items)), ("caption", String(describing: caption))]) - case .pageBlockCover(let cover): - return ("pageBlockCover", [("cover", String(describing: cover))]) - case .pageBlockDetails(let flags, let blocks, let title): - return ("pageBlockDetails", [("flags", String(describing: flags)), ("blocks", String(describing: blocks)), ("title", String(describing: title))]) - case .pageBlockDivider: - return ("pageBlockDivider", []) - case .pageBlockEmbed(let flags, let url, let html, let posterPhotoId, let w, let h, let caption): - return ("pageBlockEmbed", [("flags", String(describing: flags)), ("url", String(describing: url)), ("html", String(describing: html)), ("posterPhotoId", String(describing: posterPhotoId)), ("w", String(describing: w)), ("h", String(describing: h)), ("caption", String(describing: caption))]) - case .pageBlockEmbedPost(let url, let webpageId, let authorPhotoId, let author, let date, let blocks, let caption): - return ("pageBlockEmbedPost", [("url", String(describing: url)), ("webpageId", String(describing: webpageId)), ("authorPhotoId", String(describing: authorPhotoId)), ("author", String(describing: author)), ("date", String(describing: date)), ("blocks", String(describing: blocks)), ("caption", String(describing: caption))]) - case .pageBlockFooter(let text): - return ("pageBlockFooter", [("text", String(describing: text))]) - case .pageBlockHeader(let text): - return ("pageBlockHeader", [("text", String(describing: text))]) - case .pageBlockKicker(let text): - return ("pageBlockKicker", [("text", String(describing: text))]) - case .pageBlockList(let items): - return ("pageBlockList", [("items", String(describing: items))]) - case .pageBlockMap(let geo, let zoom, let w, let h, let caption): - return ("pageBlockMap", [("geo", String(describing: geo)), ("zoom", String(describing: zoom)), ("w", String(describing: w)), ("h", String(describing: h)), ("caption", String(describing: caption))]) - case .pageBlockOrderedList(let items): - return ("pageBlockOrderedList", [("items", String(describing: items))]) - case .pageBlockParagraph(let text): - return ("pageBlockParagraph", [("text", String(describing: text))]) - case .pageBlockPhoto(let flags, let photoId, let caption, let url, let webpageId): - return ("pageBlockPhoto", [("flags", String(describing: flags)), ("photoId", String(describing: photoId)), ("caption", String(describing: caption)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId))]) - case .pageBlockPreformatted(let text, let language): - return ("pageBlockPreformatted", [("text", String(describing: text)), ("language", String(describing: language))]) - case .pageBlockPullquote(let text, let caption): - return ("pageBlockPullquote", [("text", String(describing: text)), ("caption", String(describing: caption))]) - case .pageBlockRelatedArticles(let title, let articles): - return ("pageBlockRelatedArticles", [("title", String(describing: title)), ("articles", String(describing: articles))]) - case .pageBlockSlideshow(let items, let caption): - return ("pageBlockSlideshow", [("items", String(describing: items)), ("caption", String(describing: caption))]) - case .pageBlockSubheader(let text): - return ("pageBlockSubheader", [("text", String(describing: text))]) - case .pageBlockSubtitle(let text): - return ("pageBlockSubtitle", [("text", String(describing: text))]) - case .pageBlockTable(let flags, let title, let rows): - return ("pageBlockTable", [("flags", String(describing: flags)), ("title", String(describing: title)), ("rows", String(describing: rows))]) - case .pageBlockTitle(let text): - return ("pageBlockTitle", [("text", String(describing: text))]) - case .pageBlockUnsupported: - return ("pageBlockUnsupported", []) - case .pageBlockVideo(let flags, let videoId, let caption): - return ("pageBlockVideo", [("flags", String(describing: flags)), ("videoId", String(describing: videoId)), ("caption", String(describing: caption))]) + case .messageRange(let minId, let maxId): + return ("messageRange", [("minId", String(describing: minId)), ("maxId", String(describing: maxId))]) } } - public static func parse_pageBlockAnchor(_ reader: BufferReader) -> PageBlock? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockAnchor(name: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockAudio(_ reader: BufferReader) -> PageBlock? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.PageCaption? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockAudio(audioId: _1!, caption: _2!) - } - else { - return nil - } - } - public static func parse_pageBlockAuthorDate(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } + public static func parse_messageRange(_ reader: BufferReader) -> MessageRange? { + var _1: Int32? + _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.PageBlock.pageBlockAuthorDate(author: _1!, publishedDate: _2!) + return Api.MessageRange.messageRange(minId: _1!, maxId: _2!) } else { return nil } } - public static func parse_pageBlockBlockquote(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: Api.RichText? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockBlockquote(text: _1!, caption: _2!) - } - else { - return nil - } - } - public static func parse_pageBlockChannel(_ reader: BufferReader) -> PageBlock? { - var _1: Api.Chat? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Chat - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockChannel(channel: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockCollage(_ reader: BufferReader) -> PageBlock? { - var _1: [Api.PageBlock]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - var _2: Api.PageCaption? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockCollage(items: _1!, caption: _2!) - } - else { - return nil - } - } - public static func parse_pageBlockCover(_ reader: BufferReader) -> PageBlock? { - var _1: Api.PageBlock? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PageBlock - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockCover(cover: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockDetails(_ reader: BufferReader) -> PageBlock? { + + } +} +public extension Api { + enum MessageReactions: TypeConstructorDescription { + case messageReactions(flags: Int32, results: [Api.ReactionCount], recentReactions: [Api.MessagePeerReaction]?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageReactions(let flags, let results, let recentReactions): + if boxed { + buffer.appendInt32(1328256121) + } + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(results.count)) + for item in results { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(recentReactions!.count)) + for item in recentReactions! { + item.serialize(buffer, true) + }} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageReactions(let flags, let results, let recentReactions): + return ("messageReactions", [("flags", String(describing: flags)), ("results", String(describing: results)), ("recentReactions", String(describing: recentReactions))]) + } + } + + public static func parse_messageReactions(_ reader: BufferReader) -> MessageReactions? { var _1: Int32? _1 = reader.readInt32() - var _2: [Api.PageBlock]? + var _2: [Api.ReactionCount]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - var _3: Api.RichText? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.RichText + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ReactionCount.self) } + var _3: [Api.MessagePeerReaction]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessagePeerReaction.self) + } } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil if _c1 && _c2 && _c3 { - return Api.PageBlock.pageBlockDetails(flags: _1!, blocks: _2!, title: _3!) + return Api.MessageReactions.messageReactions(flags: _1!, results: _2!, recentReactions: _3) } else { return nil } } - public static func parse_pageBlockDivider(_ reader: BufferReader) -> PageBlock? { - return Api.PageBlock.pageBlockDivider - } - public static func parse_pageBlockEmbed(_ reader: BufferReader) -> PageBlock? { + + } +} +public extension Api { + enum MessageReplies: TypeConstructorDescription { + case messageReplies(flags: Int32, replies: Int32, repliesPts: Int32, recentRepliers: [Api.Peer]?, channelId: Int64?, maxId: Int32?, readMaxId: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageReplies(let flags, let replies, let repliesPts, let recentRepliers, let channelId, let maxId, let readMaxId): + if boxed { + buffer.appendInt32(-2083123262) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(replies, buffer: buffer, boxed: false) + serializeInt32(repliesPts, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(recentRepliers!.count)) + for item in recentRepliers! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 0) != 0 {serializeInt64(channelId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(readMaxId!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageReplies(let flags, let replies, let repliesPts, let recentRepliers, let channelId, let maxId, let readMaxId): + return ("messageReplies", [("flags", String(describing: flags)), ("replies", String(describing: replies)), ("repliesPts", String(describing: repliesPts)), ("recentRepliers", String(describing: recentRepliers)), ("channelId", String(describing: channelId)), ("maxId", String(describing: maxId)), ("readMaxId", String(describing: readMaxId))]) + } + } + + public static func parse_messageReplies(_ reader: BufferReader) -> MessageReplies? { var _1: Int32? _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 1) != 0 {_2 = parseString(reader) } - var _3: String? - if Int(_1!) & Int(1 << 2) != 0 {_3 = parseString(reader) } - var _4: Int64? - if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() } - var _5: Int32? - if Int(_1!) & Int(1 << 5) != 0 {_5 = reader.readInt32() } - var _6: Int32? - if Int(_1!) & Int(1 << 5) != 0 {_6 = reader.readInt32() } - var _7: Api.PageCaption? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 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 << 5) == 0) || _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.PageBlock.pageBlockEmbed(flags: _1!, url: _2, html: _3, posterPhotoId: _4, w: _5, h: _6, caption: _7!) - } - else { - return nil - } - } - public static func parse_pageBlockEmbedPost(_ reader: BufferReader) -> PageBlock? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: Int32? - _5 = reader.readInt32() - var _6: [Api.PageBlock]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - var _7: Api.PageCaption? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.PageBlock.pageBlockEmbedPost(url: _1!, webpageId: _2!, authorPhotoId: _3!, author: _4!, date: _5!, blocks: _6!, caption: _7!) - } - else { - return nil - } - } - public static func parse_pageBlockFooter(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockFooter(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockHeader(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockHeader(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockKicker(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockKicker(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockList(_ reader: BufferReader) -> PageBlock? { - var _1: [Api.PageListItem]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageListItem.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockList(items: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockMap(_ reader: BufferReader) -> PageBlock? { - var _1: Api.GeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } var _2: Int32? _2 = reader.readInt32() var _3: Int32? _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Api.PageCaption? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.PageBlock.pageBlockMap(geo: _1!, zoom: _2!, w: _3!, h: _4!, caption: _5!) - } - else { - return nil - } - } - public static func parse_pageBlockOrderedList(_ reader: BufferReader) -> PageBlock? { - var _1: [Api.PageListOrderedItem]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageListOrderedItem.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockOrderedList(items: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockParagraph(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockParagraph(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockPhoto(_ reader: BufferReader) -> PageBlock? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.PageCaption? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - var _4: String? - if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } + var _4: [Api.Peer]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + } } var _5: Int64? if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } + var _6: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() } + var _7: Int32? + if Int(_1!) & Int(1 << 3) != 0 {_7 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.PageBlock.pageBlockPhoto(flags: _1!, photoId: _2!, caption: _3!, url: _4, webpageId: _5) + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.MessageReplies.messageReplies(flags: _1!, replies: _2!, repliesPts: _3!, recentRepliers: _4, channelId: _5, maxId: _6, readMaxId: _7) } else { return nil } } - public static func parse_pageBlockPreformatted(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText + + } +} +public extension Api { + enum MessageReplyHeader: TypeConstructorDescription { + case messageReplyHeader(flags: Int32, replyToMsgId: Int32, replyToPeerId: Api.Peer?, replyToTopId: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageReplyHeader(let flags, let replyToMsgId, let replyToPeerId, let replyToTopId): + if boxed { + buffer.appendInt32(-1495959709) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(replyToMsgId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {replyToPeerId!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(replyToTopId!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageReplyHeader(let flags, let replyToMsgId, let replyToPeerId, let replyToTopId): + return ("messageReplyHeader", [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("replyToPeerId", String(describing: replyToPeerId)), ("replyToTopId", String(describing: replyToTopId))]) + } + } + + public static func parse_messageReplyHeader(_ reader: BufferReader) -> MessageReplyHeader? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.Peer? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer + } } + var _4: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageReplyHeader.messageReplyHeader(flags: _1!, replyToMsgId: _2!, replyToPeerId: _3, replyToTopId: _4) } + else { + return nil + } + } + + } +} +public extension Api { + enum MessageUserVote: TypeConstructorDescription { + case messageUserVote(userId: Int64, option: Buffer, date: Int32) + case messageUserVoteInputOption(userId: Int64, date: Int32) + case messageUserVoteMultiple(userId: Int64, options: [Buffer], date: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageUserVote(let userId, let option, let date): + if boxed { + buffer.appendInt32(886196148) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeBytes(option, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .messageUserVoteInputOption(let userId, let date): + if boxed { + buffer.appendInt32(1017491692) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .messageUserVoteMultiple(let userId, let options, let date): + if boxed { + buffer.appendInt32(-1973033641) + } + serializeInt64(userId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(options.count)) + for item in options { + serializeBytes(item, buffer: buffer, boxed: false) + } + serializeInt32(date, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageUserVote(let userId, let option, let date): + return ("messageUserVote", [("userId", String(describing: userId)), ("option", String(describing: option)), ("date", String(describing: date))]) + case .messageUserVoteInputOption(let userId, let date): + return ("messageUserVoteInputOption", [("userId", String(describing: userId)), ("date", String(describing: date))]) + case .messageUserVoteMultiple(let userId, let options, let date): + return ("messageUserVoteMultiple", [("userId", String(describing: userId)), ("options", String(describing: options)), ("date", String(describing: date))]) + } + } + + public static func parse_messageUserVote(_ reader: BufferReader) -> MessageUserVote? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageUserVote.messageUserVote(userId: _1!, option: _2!, date: _3!) + } + else { + return nil + } + } + public static func parse_messageUserVoteInputOption(_ reader: BufferReader) -> MessageUserVote? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageUserVote.messageUserVoteInputOption(userId: _1!, date: _2!) + } + else { + return nil + } + } + public static func parse_messageUserVoteMultiple(_ reader: BufferReader) -> MessageUserVote? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Buffer]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) + } + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.MessageUserVote.messageUserVoteMultiple(userId: _1!, options: _2!, date: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum MessageViews: TypeConstructorDescription { + case messageViews(flags: Int32, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageViews(let flags, let views, let forwards, let replies): + if boxed { + buffer.appendInt32(1163625789) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(forwards!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {replies!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageViews(let flags, let views, let forwards, let replies): + return ("messageViews", [("flags", String(describing: flags)), ("views", String(describing: views)), ("forwards", String(describing: forwards)), ("replies", String(describing: replies))]) + } + } + + public static func parse_messageViews(_ reader: BufferReader) -> MessageViews? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + var _4: Api.MessageReplies? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.MessageReplies + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageViews.messageViews(flags: _1!, views: _2, forwards: _3, replies: _4) + } + else { + return nil + } + } + + } +} +public extension Api { + enum MessagesFilter: TypeConstructorDescription { + case inputMessagesFilterChatPhotos + case inputMessagesFilterContacts + case inputMessagesFilterDocument + case inputMessagesFilterEmpty + case inputMessagesFilterGeo + case inputMessagesFilterGif + case inputMessagesFilterMusic + case inputMessagesFilterMyMentions + case inputMessagesFilterPhoneCalls(flags: Int32) + case inputMessagesFilterPhotoVideo + case inputMessagesFilterPhotos + case inputMessagesFilterPinned + case inputMessagesFilterRoundVideo + case inputMessagesFilterRoundVoice + case inputMessagesFilterUrl + case inputMessagesFilterVideo + case inputMessagesFilterVoice + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputMessagesFilterChatPhotos: + if boxed { + buffer.appendInt32(975236280) + } + + break + case .inputMessagesFilterContacts: + if boxed { + buffer.appendInt32(-530392189) + } + + break + case .inputMessagesFilterDocument: + if boxed { + buffer.appendInt32(-1629621880) + } + + break + case .inputMessagesFilterEmpty: + if boxed { + buffer.appendInt32(1474492012) + } + + break + case .inputMessagesFilterGeo: + if boxed { + buffer.appendInt32(-419271411) + } + + break + case .inputMessagesFilterGif: + if boxed { + buffer.appendInt32(-3644025) + } + + break + case .inputMessagesFilterMusic: + if boxed { + buffer.appendInt32(928101534) + } + + break + case .inputMessagesFilterMyMentions: + if boxed { + buffer.appendInt32(-1040652646) + } + + break + case .inputMessagesFilterPhoneCalls(let flags): + if boxed { + buffer.appendInt32(-2134272152) + } + serializeInt32(flags, buffer: buffer, boxed: false) + break + case .inputMessagesFilterPhotoVideo: + if boxed { + buffer.appendInt32(1458172132) + } + + break + case .inputMessagesFilterPhotos: + if boxed { + buffer.appendInt32(-1777752804) + } + + break + case .inputMessagesFilterPinned: + if boxed { + buffer.appendInt32(464520273) + } + + break + case .inputMessagesFilterRoundVideo: + if boxed { + buffer.appendInt32(-1253451181) + } + + break + case .inputMessagesFilterRoundVoice: + if boxed { + buffer.appendInt32(2054952868) + } + + break + case .inputMessagesFilterUrl: + if boxed { + buffer.appendInt32(2129714567) + } + + break + case .inputMessagesFilterVideo: + if boxed { + buffer.appendInt32(-1614803355) + } + + break + case .inputMessagesFilterVoice: + if boxed { + buffer.appendInt32(1358283666) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputMessagesFilterChatPhotos: + return ("inputMessagesFilterChatPhotos", []) + case .inputMessagesFilterContacts: + return ("inputMessagesFilterContacts", []) + case .inputMessagesFilterDocument: + return ("inputMessagesFilterDocument", []) + case .inputMessagesFilterEmpty: + return ("inputMessagesFilterEmpty", []) + case .inputMessagesFilterGeo: + return ("inputMessagesFilterGeo", []) + case .inputMessagesFilterGif: + return ("inputMessagesFilterGif", []) + case .inputMessagesFilterMusic: + return ("inputMessagesFilterMusic", []) + case .inputMessagesFilterMyMentions: + return ("inputMessagesFilterMyMentions", []) + case .inputMessagesFilterPhoneCalls(let flags): + return ("inputMessagesFilterPhoneCalls", [("flags", String(describing: flags))]) + case .inputMessagesFilterPhotoVideo: + return ("inputMessagesFilterPhotoVideo", []) + case .inputMessagesFilterPhotos: + return ("inputMessagesFilterPhotos", []) + case .inputMessagesFilterPinned: + return ("inputMessagesFilterPinned", []) + case .inputMessagesFilterRoundVideo: + return ("inputMessagesFilterRoundVideo", []) + case .inputMessagesFilterRoundVoice: + return ("inputMessagesFilterRoundVoice", []) + case .inputMessagesFilterUrl: + return ("inputMessagesFilterUrl", []) + case .inputMessagesFilterVideo: + return ("inputMessagesFilterVideo", []) + case .inputMessagesFilterVoice: + return ("inputMessagesFilterVoice", []) + } + } + + public static func parse_inputMessagesFilterChatPhotos(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterChatPhotos + } + public static func parse_inputMessagesFilterContacts(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterContacts + } + public static func parse_inputMessagesFilterDocument(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterDocument + } + public static func parse_inputMessagesFilterEmpty(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterEmpty + } + public static func parse_inputMessagesFilterGeo(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterGeo + } + public static func parse_inputMessagesFilterGif(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterGif + } + public static func parse_inputMessagesFilterMusic(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterMusic + } + public static func parse_inputMessagesFilterMyMentions(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterMyMentions + } + public static func parse_inputMessagesFilterPhoneCalls(_ reader: BufferReader) -> MessagesFilter? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.MessagesFilter.inputMessagesFilterPhoneCalls(flags: _1!) + } + else { + return nil + } + } + public static func parse_inputMessagesFilterPhotoVideo(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterPhotoVideo + } + public static func parse_inputMessagesFilterPhotos(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterPhotos + } + public static func parse_inputMessagesFilterPinned(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterPinned + } + public static func parse_inputMessagesFilterRoundVideo(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterRoundVideo + } + public static func parse_inputMessagesFilterRoundVoice(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterRoundVoice + } + public static func parse_inputMessagesFilterUrl(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterUrl + } + public static func parse_inputMessagesFilterVideo(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterVideo + } + public static func parse_inputMessagesFilterVoice(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterVoice + } + + } +} +public extension Api { + enum NearestDc: TypeConstructorDescription { + case nearestDc(country: String, thisDc: Int32, nearestDc: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .nearestDc(let country, let thisDc, let nearestDc): + if boxed { + buffer.appendInt32(-1910892683) + } + serializeString(country, buffer: buffer, boxed: false) + serializeInt32(thisDc, buffer: buffer, boxed: false) + serializeInt32(nearestDc, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .nearestDc(let country, let thisDc, let nearestDc): + return ("nearestDc", [("country", String(describing: country)), ("thisDc", String(describing: thisDc)), ("nearestDc", String(describing: nearestDc))]) + } + } + + public static func parse_nearestDc(_ reader: BufferReader) -> NearestDc? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.NearestDc.nearestDc(country: _1!, thisDc: _2!, nearestDc: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum NotificationSound: TypeConstructorDescription { + case notificationSoundDefault + case notificationSoundLocal(title: String, data: String) + case notificationSoundNone + case notificationSoundRingtone(id: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .notificationSoundDefault: + if boxed { + buffer.appendInt32(-1746354498) + } + + break + case .notificationSoundLocal(let title, let data): + if boxed { + buffer.appendInt32(-2096391452) + } + serializeString(title, buffer: buffer, boxed: false) + serializeString(data, buffer: buffer, boxed: false) + break + case .notificationSoundNone: + if boxed { + buffer.appendInt32(1863070943) + } + + break + case .notificationSoundRingtone(let id): + if boxed { + buffer.appendInt32(-9666487) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .notificationSoundDefault: + return ("notificationSoundDefault", []) + case .notificationSoundLocal(let title, let data): + return ("notificationSoundLocal", [("title", String(describing: title)), ("data", String(describing: data))]) + case .notificationSoundNone: + return ("notificationSoundNone", []) + case .notificationSoundRingtone(let id): + return ("notificationSoundRingtone", [("id", String(describing: id))]) + } + } + + public static func parse_notificationSoundDefault(_ reader: BufferReader) -> NotificationSound? { + return Api.NotificationSound.notificationSoundDefault + } + public static func parse_notificationSoundLocal(_ reader: BufferReader) -> NotificationSound? { + var _1: String? + _1 = parseString(reader) var _2: String? _2 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.PageBlock.pageBlockPreformatted(text: _1!, language: _2!) + return Api.NotificationSound.notificationSoundLocal(title: _1!, data: _2!) } else { return nil } } - public static func parse_pageBlockPullquote(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: Api.RichText? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockPullquote(text: _1!, caption: _2!) - } - else { - return nil - } + public static func parse_notificationSoundNone(_ reader: BufferReader) -> NotificationSound? { + return Api.NotificationSound.notificationSoundNone } - public static func parse_pageBlockRelatedArticles(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: [Api.PageRelatedArticle]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageRelatedArticle.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockRelatedArticles(title: _1!, articles: _2!) - } - else { - return nil - } - } - public static func parse_pageBlockSlideshow(_ reader: BufferReader) -> PageBlock? { - var _1: [Api.PageBlock]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - var _2: Api.PageCaption? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageBlock.pageBlockSlideshow(items: _1!, caption: _2!) - } - else { - return nil - } - } - public static func parse_pageBlockSubheader(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } + public static func parse_notificationSoundRingtone(_ reader: BufferReader) -> NotificationSound? { + var _1: Int64? + _1 = reader.readInt64() let _c1 = _1 != nil if _c1 { - return Api.PageBlock.pageBlockSubheader(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockSubtitle(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockSubtitle(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockTable(_ reader: BufferReader) -> PageBlock? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.RichText? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _3: [Api.PageTableRow]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageTableRow.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.PageBlock.pageBlockTable(flags: _1!, title: _2!, rows: _3!) - } - else { - return nil - } - } - public static func parse_pageBlockTitle(_ reader: BufferReader) -> PageBlock? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageBlock.pageBlockTitle(text: _1!) - } - else { - return nil - } - } - public static func parse_pageBlockUnsupported(_ reader: BufferReader) -> PageBlock? { - return Api.PageBlock.pageBlockUnsupported - } - public static func parse_pageBlockVideo(_ reader: BufferReader) -> PageBlock? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.PageCaption? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.PageCaption - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.PageBlock.pageBlockVideo(flags: _1!, videoId: _2!, caption: _3!) + return Api.NotificationSound.notificationSoundRingtone(id: _1!) } else { return nil @@ -891,110 +765,76 @@ public extension Api { } } public extension Api { - enum PageCaption: TypeConstructorDescription { - case pageCaption(text: Api.RichText, credit: Api.RichText) + enum NotifyPeer: TypeConstructorDescription { + case notifyBroadcasts + case notifyChats + case notifyPeer(peer: Api.Peer) + case notifyUsers public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .pageCaption(let text, let credit): + case .notifyBroadcasts: if boxed { - buffer.appendInt32(1869903447) + buffer.appendInt32(-703403793) } - text.serialize(buffer, true) - credit.serialize(buffer, true) + + break + case .notifyChats: + if boxed { + buffer.appendInt32(-1073230141) + } + + break + case .notifyPeer(let peer): + if boxed { + buffer.appendInt32(-1613493288) + } + peer.serialize(buffer, true) + break + case .notifyUsers: + if boxed { + buffer.appendInt32(-1261946036) + } + break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .pageCaption(let text, let credit): - return ("pageCaption", [("text", String(describing: text)), ("credit", String(describing: credit))]) + case .notifyBroadcasts: + return ("notifyBroadcasts", []) + case .notifyChats: + return ("notifyChats", []) + case .notifyPeer(let peer): + return ("notifyPeer", [("peer", String(describing: peer))]) + case .notifyUsers: + return ("notifyUsers", []) } } - public static func parse_pageCaption(_ reader: BufferReader) -> PageCaption? { - var _1: Api.RichText? + public static func parse_notifyBroadcasts(_ reader: BufferReader) -> NotifyPeer? { + return Api.NotifyPeer.notifyBroadcasts + } + public static func parse_notifyChats(_ reader: BufferReader) -> NotifyPeer? { + return Api.NotifyPeer.notifyChats + } + public static func parse_notifyPeer(_ reader: BufferReader) -> NotifyPeer? { + var _1: Api.Peer? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: Api.RichText? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText + _1 = Api.parse(reader, signature: signature) as? Api.Peer } let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageCaption.pageCaption(text: _1!, credit: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PageListItem: TypeConstructorDescription { - case pageListItemBlocks(blocks: [Api.PageBlock]) - case pageListItemText(text: Api.RichText) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pageListItemBlocks(let blocks): - if boxed { - buffer.appendInt32(635466748) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocks.count)) - for item in blocks { - item.serialize(buffer, true) - } - break - case .pageListItemText(let text): - if boxed { - buffer.appendInt32(-1188055347) - } - text.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pageListItemBlocks(let blocks): - return ("pageListItemBlocks", [("blocks", String(describing: blocks))]) - case .pageListItemText(let text): - return ("pageListItemText", [("text", String(describing: text))]) - } - } - - public static func parse_pageListItemBlocks(_ reader: BufferReader) -> PageListItem? { - var _1: [Api.PageBlock]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PageListItem.pageListItemBlocks(blocks: _1!) - } - else { - return nil - } - } - public static func parse_pageListItemText(_ reader: BufferReader) -> PageListItem? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.PageListItem.pageListItemText(text: _1!) + if _c1 { + return Api.NotifyPeer.notifyPeer(peer: _1!) } else { return nil } } + public static func parse_notifyUsers(_ reader: BufferReader) -> NotifyPeer? { + return Api.NotifyPeer.notifyUsers + } } } diff --git a/submodules/TelegramApi/Sources/Api14.swift b/submodules/TelegramApi/Sources/Api14.swift index d25de327ff..4a985aec2a 100644 --- a/submodules/TelegramApi/Sources/Api14.swift +++ b/submodules/TelegramApi/Sources/Api14.swift @@ -1,26 +1,960 @@ public extension Api { - enum PageListOrderedItem: TypeConstructorDescription { - case pageListOrderedItemBlocks(num: String, blocks: [Api.PageBlock]) - case pageListOrderedItemText(num: String, text: Api.RichText) + enum Page: TypeConstructorDescription { + case page(flags: Int32, url: String, blocks: [Api.PageBlock], photos: [Api.Photo], documents: [Api.Document], views: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .pageListOrderedItemBlocks(let num, let blocks): + case .page(let flags, let url, let blocks, let photos, let documents, let views): if boxed { - buffer.appendInt32(-1730311882) + buffer.appendInt32(-1738178803) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(blocks.count)) + for item in blocks { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(photos.count)) + for item in photos { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents.count)) + for item in documents { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(views!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .page(let flags, let url, let blocks, let photos, let documents, let views): + return ("page", [("flags", String(describing: flags)), ("url", String(describing: url)), ("blocks", String(describing: blocks)), ("photos", String(describing: photos)), ("documents", String(describing: documents)), ("views", String(describing: views))]) + } + } + + public static func parse_page(_ reader: BufferReader) -> Page? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: [Api.PageBlock]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + var _4: [Api.Photo]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) + } + var _5: [Api.Document]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + var _6: Int32? + if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Page.page(flags: _1!, url: _2!, blocks: _3!, photos: _4!, documents: _5!, views: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + indirect enum PageBlock: TypeConstructorDescription { + case pageBlockAnchor(name: String) + case pageBlockAudio(audioId: Int64, caption: Api.PageCaption) + case pageBlockAuthorDate(author: Api.RichText, publishedDate: Int32) + case pageBlockBlockquote(text: Api.RichText, caption: Api.RichText) + case pageBlockChannel(channel: Api.Chat) + case pageBlockCollage(items: [Api.PageBlock], caption: Api.PageCaption) + case pageBlockCover(cover: Api.PageBlock) + case pageBlockDetails(flags: Int32, blocks: [Api.PageBlock], title: Api.RichText) + case pageBlockDivider + case pageBlockEmbed(flags: Int32, url: String?, html: String?, posterPhotoId: Int64?, w: Int32?, h: Int32?, caption: Api.PageCaption) + case pageBlockEmbedPost(url: String, webpageId: Int64, authorPhotoId: Int64, author: String, date: Int32, blocks: [Api.PageBlock], caption: Api.PageCaption) + case pageBlockFooter(text: Api.RichText) + case pageBlockHeader(text: Api.RichText) + case pageBlockKicker(text: Api.RichText) + case pageBlockList(items: [Api.PageListItem]) + case pageBlockMap(geo: Api.GeoPoint, zoom: Int32, w: Int32, h: Int32, caption: Api.PageCaption) + case pageBlockOrderedList(items: [Api.PageListOrderedItem]) + case pageBlockParagraph(text: Api.RichText) + case pageBlockPhoto(flags: Int32, photoId: Int64, caption: Api.PageCaption, url: String?, webpageId: Int64?) + case pageBlockPreformatted(text: Api.RichText, language: String) + case pageBlockPullquote(text: Api.RichText, caption: Api.RichText) + case pageBlockRelatedArticles(title: Api.RichText, articles: [Api.PageRelatedArticle]) + case pageBlockSlideshow(items: [Api.PageBlock], caption: Api.PageCaption) + case pageBlockSubheader(text: Api.RichText) + case pageBlockSubtitle(text: Api.RichText) + case pageBlockTable(flags: Int32, title: Api.RichText, rows: [Api.PageTableRow]) + case pageBlockTitle(text: Api.RichText) + case pageBlockUnsupported + case pageBlockVideo(flags: Int32, videoId: Int64, caption: Api.PageCaption) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageBlockAnchor(let name): + if boxed { + buffer.appendInt32(-837994576) + } + serializeString(name, buffer: buffer, boxed: false) + break + case .pageBlockAudio(let audioId, let caption): + if boxed { + buffer.appendInt32(-2143067670) + } + serializeInt64(audioId, buffer: buffer, boxed: false) + caption.serialize(buffer, true) + break + case .pageBlockAuthorDate(let author, let publishedDate): + if boxed { + buffer.appendInt32(-1162877472) + } + author.serialize(buffer, true) + serializeInt32(publishedDate, buffer: buffer, boxed: false) + break + case .pageBlockBlockquote(let text, let caption): + if boxed { + buffer.appendInt32(641563686) + } + text.serialize(buffer, true) + caption.serialize(buffer, true) + break + case .pageBlockChannel(let channel): + if boxed { + buffer.appendInt32(-283684427) + } + channel.serialize(buffer, true) + break + case .pageBlockCollage(let items, let caption): + if boxed { + buffer.appendInt32(1705048653) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(items.count)) + for item in items { + item.serialize(buffer, true) + } + caption.serialize(buffer, true) + break + case .pageBlockCover(let cover): + if boxed { + buffer.appendInt32(972174080) + } + cover.serialize(buffer, true) + break + case .pageBlockDetails(let flags, let blocks, let title): + if boxed { + buffer.appendInt32(1987480557) + } + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(blocks.count)) + for item in blocks { + item.serialize(buffer, true) + } + title.serialize(buffer, true) + break + case .pageBlockDivider: + if boxed { + buffer.appendInt32(-618614392) + } + + break + case .pageBlockEmbed(let flags, let url, let html, let posterPhotoId, let w, let h, let caption): + if boxed { + buffer.appendInt32(-1468953147) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(html!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt64(posterPhotoId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {serializeInt32(w!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {serializeInt32(h!, buffer: buffer, boxed: false)} + caption.serialize(buffer, true) + break + case .pageBlockEmbedPost(let url, let webpageId, let authorPhotoId, let author, let date, let blocks, let caption): + if boxed { + buffer.appendInt32(-229005301) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(webpageId, buffer: buffer, boxed: false) + serializeInt64(authorPhotoId, buffer: buffer, boxed: false) + serializeString(author, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(blocks.count)) + for item in blocks { + item.serialize(buffer, true) + } + caption.serialize(buffer, true) + break + case .pageBlockFooter(let text): + if boxed { + buffer.appendInt32(1216809369) + } + text.serialize(buffer, true) + break + case .pageBlockHeader(let text): + if boxed { + buffer.appendInt32(-1076861716) + } + text.serialize(buffer, true) + break + case .pageBlockKicker(let text): + if boxed { + buffer.appendInt32(504660880) + } + text.serialize(buffer, true) + break + case .pageBlockList(let items): + if boxed { + buffer.appendInt32(-454524911) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(items.count)) + for item in items { + item.serialize(buffer, true) + } + break + case .pageBlockMap(let geo, let zoom, let w, let h, let caption): + if boxed { + buffer.appendInt32(-1538310410) + } + geo.serialize(buffer, true) + serializeInt32(zoom, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + caption.serialize(buffer, true) + break + case .pageBlockOrderedList(let items): + if boxed { + buffer.appendInt32(-1702174239) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(items.count)) + for item in items { + item.serialize(buffer, true) + } + break + case .pageBlockParagraph(let text): + if boxed { + buffer.appendInt32(1182402406) + } + text.serialize(buffer, true) + break + case .pageBlockPhoto(let flags, let photoId, let caption, let url, let webpageId): + if boxed { + buffer.appendInt32(391759200) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(photoId, buffer: buffer, boxed: false) + caption.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt64(webpageId!, buffer: buffer, boxed: false)} + break + case .pageBlockPreformatted(let text, let language): + if boxed { + buffer.appendInt32(-1066346178) + } + text.serialize(buffer, true) + serializeString(language, buffer: buffer, boxed: false) + break + case .pageBlockPullquote(let text, let caption): + if boxed { + buffer.appendInt32(1329878739) + } + text.serialize(buffer, true) + caption.serialize(buffer, true) + break + case .pageBlockRelatedArticles(let title, let articles): + if boxed { + buffer.appendInt32(370236054) + } + title.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(articles.count)) + for item in articles { + item.serialize(buffer, true) + } + break + case .pageBlockSlideshow(let items, let caption): + if boxed { + buffer.appendInt32(52401552) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(items.count)) + for item in items { + item.serialize(buffer, true) + } + caption.serialize(buffer, true) + break + case .pageBlockSubheader(let text): + if boxed { + buffer.appendInt32(-248793375) + } + text.serialize(buffer, true) + break + case .pageBlockSubtitle(let text): + if boxed { + buffer.appendInt32(-1879401953) + } + text.serialize(buffer, true) + break + case .pageBlockTable(let flags, let title, let rows): + if boxed { + buffer.appendInt32(-1085412734) + } + serializeInt32(flags, buffer: buffer, boxed: false) + title.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rows.count)) + for item in rows { + item.serialize(buffer, true) + } + break + case .pageBlockTitle(let text): + if boxed { + buffer.appendInt32(1890305021) + } + text.serialize(buffer, true) + break + case .pageBlockUnsupported: + if boxed { + buffer.appendInt32(324435594) + } + + break + case .pageBlockVideo(let flags, let videoId, let caption): + if boxed { + buffer.appendInt32(2089805750) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(videoId, buffer: buffer, boxed: false) + caption.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pageBlockAnchor(let name): + return ("pageBlockAnchor", [("name", String(describing: name))]) + case .pageBlockAudio(let audioId, let caption): + return ("pageBlockAudio", [("audioId", String(describing: audioId)), ("caption", String(describing: caption))]) + case .pageBlockAuthorDate(let author, let publishedDate): + return ("pageBlockAuthorDate", [("author", String(describing: author)), ("publishedDate", String(describing: publishedDate))]) + case .pageBlockBlockquote(let text, let caption): + return ("pageBlockBlockquote", [("text", String(describing: text)), ("caption", String(describing: caption))]) + case .pageBlockChannel(let channel): + return ("pageBlockChannel", [("channel", String(describing: channel))]) + case .pageBlockCollage(let items, let caption): + return ("pageBlockCollage", [("items", String(describing: items)), ("caption", String(describing: caption))]) + case .pageBlockCover(let cover): + return ("pageBlockCover", [("cover", String(describing: cover))]) + case .pageBlockDetails(let flags, let blocks, let title): + return ("pageBlockDetails", [("flags", String(describing: flags)), ("blocks", String(describing: blocks)), ("title", String(describing: title))]) + case .pageBlockDivider: + return ("pageBlockDivider", []) + case .pageBlockEmbed(let flags, let url, let html, let posterPhotoId, let w, let h, let caption): + return ("pageBlockEmbed", [("flags", String(describing: flags)), ("url", String(describing: url)), ("html", String(describing: html)), ("posterPhotoId", String(describing: posterPhotoId)), ("w", String(describing: w)), ("h", String(describing: h)), ("caption", String(describing: caption))]) + case .pageBlockEmbedPost(let url, let webpageId, let authorPhotoId, let author, let date, let blocks, let caption): + return ("pageBlockEmbedPost", [("url", String(describing: url)), ("webpageId", String(describing: webpageId)), ("authorPhotoId", String(describing: authorPhotoId)), ("author", String(describing: author)), ("date", String(describing: date)), ("blocks", String(describing: blocks)), ("caption", String(describing: caption))]) + case .pageBlockFooter(let text): + return ("pageBlockFooter", [("text", String(describing: text))]) + case .pageBlockHeader(let text): + return ("pageBlockHeader", [("text", String(describing: text))]) + case .pageBlockKicker(let text): + return ("pageBlockKicker", [("text", String(describing: text))]) + case .pageBlockList(let items): + return ("pageBlockList", [("items", String(describing: items))]) + case .pageBlockMap(let geo, let zoom, let w, let h, let caption): + return ("pageBlockMap", [("geo", String(describing: geo)), ("zoom", String(describing: zoom)), ("w", String(describing: w)), ("h", String(describing: h)), ("caption", String(describing: caption))]) + case .pageBlockOrderedList(let items): + return ("pageBlockOrderedList", [("items", String(describing: items))]) + case .pageBlockParagraph(let text): + return ("pageBlockParagraph", [("text", String(describing: text))]) + case .pageBlockPhoto(let flags, let photoId, let caption, let url, let webpageId): + return ("pageBlockPhoto", [("flags", String(describing: flags)), ("photoId", String(describing: photoId)), ("caption", String(describing: caption)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId))]) + case .pageBlockPreformatted(let text, let language): + return ("pageBlockPreformatted", [("text", String(describing: text)), ("language", String(describing: language))]) + case .pageBlockPullquote(let text, let caption): + return ("pageBlockPullquote", [("text", String(describing: text)), ("caption", String(describing: caption))]) + case .pageBlockRelatedArticles(let title, let articles): + return ("pageBlockRelatedArticles", [("title", String(describing: title)), ("articles", String(describing: articles))]) + case .pageBlockSlideshow(let items, let caption): + return ("pageBlockSlideshow", [("items", String(describing: items)), ("caption", String(describing: caption))]) + case .pageBlockSubheader(let text): + return ("pageBlockSubheader", [("text", String(describing: text))]) + case .pageBlockSubtitle(let text): + return ("pageBlockSubtitle", [("text", String(describing: text))]) + case .pageBlockTable(let flags, let title, let rows): + return ("pageBlockTable", [("flags", String(describing: flags)), ("title", String(describing: title)), ("rows", String(describing: rows))]) + case .pageBlockTitle(let text): + return ("pageBlockTitle", [("text", String(describing: text))]) + case .pageBlockUnsupported: + return ("pageBlockUnsupported", []) + case .pageBlockVideo(let flags, let videoId, let caption): + return ("pageBlockVideo", [("flags", String(describing: flags)), ("videoId", String(describing: videoId)), ("caption", String(describing: caption))]) + } + } + + public static func parse_pageBlockAnchor(_ reader: BufferReader) -> PageBlock? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockAnchor(name: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockAudio(_ reader: BufferReader) -> PageBlock? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.PageCaption? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockAudio(audioId: _1!, caption: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockAuthorDate(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockAuthorDate(author: _1!, publishedDate: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockBlockquote(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: Api.RichText? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockBlockquote(text: _1!, caption: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockChannel(_ reader: BufferReader) -> PageBlock? { + var _1: Api.Chat? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Chat + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockChannel(channel: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockCollage(_ reader: BufferReader) -> PageBlock? { + var _1: [Api.PageBlock]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + var _2: Api.PageCaption? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockCollage(items: _1!, caption: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockCover(_ reader: BufferReader) -> PageBlock? { + var _1: Api.PageBlock? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PageBlock + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockCover(cover: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockDetails(_ reader: BufferReader) -> PageBlock? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.PageBlock]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + var _3: Api.RichText? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.PageBlock.pageBlockDetails(flags: _1!, blocks: _2!, title: _3!) + } + else { + return nil + } + } + public static func parse_pageBlockDivider(_ reader: BufferReader) -> PageBlock? { + return Api.PageBlock.pageBlockDivider + } + public static func parse_pageBlockEmbed(_ reader: BufferReader) -> PageBlock? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 1) != 0 {_2 = parseString(reader) } + var _3: String? + if Int(_1!) & Int(1 << 2) != 0 {_3 = parseString(reader) } + var _4: Int64? + if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() } + var _5: Int32? + if Int(_1!) & Int(1 << 5) != 0 {_5 = reader.readInt32() } + var _6: Int32? + if Int(_1!) & Int(1 << 5) != 0 {_6 = reader.readInt32() } + var _7: Api.PageCaption? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 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 << 5) == 0) || _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.PageBlock.pageBlockEmbed(flags: _1!, url: _2, html: _3, posterPhotoId: _4, w: _5, h: _6, caption: _7!) + } + else { + return nil + } + } + public static func parse_pageBlockEmbedPost(_ reader: BufferReader) -> PageBlock? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: [Api.PageBlock]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + var _7: Api.PageCaption? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.PageBlock.pageBlockEmbedPost(url: _1!, webpageId: _2!, authorPhotoId: _3!, author: _4!, date: _5!, blocks: _6!, caption: _7!) + } + else { + return nil + } + } + public static func parse_pageBlockFooter(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockFooter(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockHeader(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockHeader(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockKicker(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockKicker(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockList(_ reader: BufferReader) -> PageBlock? { + var _1: [Api.PageListItem]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageListItem.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockList(items: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockMap(_ reader: BufferReader) -> PageBlock? { + var _1: Api.GeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Api.PageCaption? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.PageBlock.pageBlockMap(geo: _1!, zoom: _2!, w: _3!, h: _4!, caption: _5!) + } + else { + return nil + } + } + public static func parse_pageBlockOrderedList(_ reader: BufferReader) -> PageBlock? { + var _1: [Api.PageListOrderedItem]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageListOrderedItem.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockOrderedList(items: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockParagraph(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockParagraph(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockPhoto(_ reader: BufferReader) -> PageBlock? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.PageCaption? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + var _4: String? + if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } + var _5: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.PageBlock.pageBlockPhoto(flags: _1!, photoId: _2!, caption: _3!, url: _4, webpageId: _5) + } + else { + return nil + } + } + public static func parse_pageBlockPreformatted(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockPreformatted(text: _1!, language: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockPullquote(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: Api.RichText? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockPullquote(text: _1!, caption: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockRelatedArticles(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: [Api.PageRelatedArticle]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageRelatedArticle.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockRelatedArticles(title: _1!, articles: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockSlideshow(_ reader: BufferReader) -> PageBlock? { + var _1: [Api.PageBlock]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + var _2: Api.PageCaption? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageBlock.pageBlockSlideshow(items: _1!, caption: _2!) + } + else { + return nil + } + } + public static func parse_pageBlockSubheader(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockSubheader(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockSubtitle(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockSubtitle(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockTable(_ reader: BufferReader) -> PageBlock? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.RichText? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _3: [Api.PageTableRow]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageTableRow.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.PageBlock.pageBlockTable(flags: _1!, title: _2!, rows: _3!) + } + else { + return nil + } + } + public static func parse_pageBlockTitle(_ reader: BufferReader) -> PageBlock? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.PageBlock.pageBlockTitle(text: _1!) + } + else { + return nil + } + } + public static func parse_pageBlockUnsupported(_ reader: BufferReader) -> PageBlock? { + return Api.PageBlock.pageBlockUnsupported + } + public static func parse_pageBlockVideo(_ reader: BufferReader) -> PageBlock? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.PageCaption? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.PageCaption + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.PageBlock.pageBlockVideo(flags: _1!, videoId: _2!, caption: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PageCaption: TypeConstructorDescription { + case pageCaption(text: Api.RichText, credit: Api.RichText) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageCaption(let text, let credit): + if boxed { + buffer.appendInt32(1869903447) + } + text.serialize(buffer, true) + credit.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pageCaption(let text, let credit): + return ("pageCaption", [("text", String(describing: text)), ("credit", String(describing: credit))]) + } + } + + public static func parse_pageCaption(_ reader: BufferReader) -> PageCaption? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: Api.RichText? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageCaption.pageCaption(text: _1!, credit: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PageListItem: TypeConstructorDescription { + case pageListItemBlocks(blocks: [Api.PageBlock]) + case pageListItemText(text: Api.RichText) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageListItemBlocks(let blocks): + if boxed { + buffer.appendInt32(635466748) } - serializeString(num, buffer: buffer, boxed: false) buffer.appendInt32(481674261) buffer.appendInt32(Int32(blocks.count)) for item in blocks { item.serialize(buffer, true) } break - case .pageListOrderedItemText(let num, let text): + case .pageListItemText(let text): if boxed { - buffer.appendInt32(1577484359) + buffer.appendInt32(-1188055347) } - serializeString(num, buffer: buffer, boxed: false) text.serialize(buffer, true) break } @@ -28,1294 +962,34 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .pageListOrderedItemBlocks(let num, let blocks): - return ("pageListOrderedItemBlocks", [("num", String(describing: num)), ("blocks", String(describing: blocks))]) - case .pageListOrderedItemText(let num, let text): - return ("pageListOrderedItemText", [("num", String(describing: num)), ("text", String(describing: text))]) + case .pageListItemBlocks(let blocks): + return ("pageListItemBlocks", [("blocks", String(describing: blocks))]) + case .pageListItemText(let text): + return ("pageListItemText", [("text", String(describing: text))]) } } - public static func parse_pageListOrderedItemBlocks(_ reader: BufferReader) -> PageListOrderedItem? { - var _1: String? - _1 = parseString(reader) - var _2: [Api.PageBlock]? + public static func parse_pageListItemBlocks(_ reader: BufferReader) -> PageListItem? { + var _1: [Api.PageBlock]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageListOrderedItem.pageListOrderedItemBlocks(num: _1!, blocks: _2!) - } - else { - return nil - } - } - public static func parse_pageListOrderedItemText(_ reader: BufferReader) -> PageListOrderedItem? { - var _1: String? - _1 = parseString(reader) - var _2: Api.RichText? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PageListOrderedItem.pageListOrderedItemText(num: _1!, text: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PageRelatedArticle: TypeConstructorDescription { - case pageRelatedArticle(flags: Int32, url: String, webpageId: Int64, title: String?, description: String?, photoId: Int64?, author: String?, publishedDate: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate): - if boxed { - buffer.appendInt32(-1282352120) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - serializeInt64(webpageId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt64(photoId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(author!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(publishedDate!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate): - return ("pageRelatedArticle", [("flags", String(describing: flags)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photoId", String(describing: photoId)), ("author", String(describing: author)), ("publishedDate", String(describing: publishedDate))]) - } - } - - public static func parse_pageRelatedArticle(_ reader: BufferReader) -> PageRelatedArticle? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } - var _5: String? - if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) } - var _6: Int64? - if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt64() } - var _7: String? - if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) } - var _8: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.PageRelatedArticle.pageRelatedArticle(flags: _1!, url: _2!, webpageId: _3!, title: _4, description: _5, photoId: _6, author: _7, publishedDate: _8) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PageTableCell: TypeConstructorDescription { - case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pageTableCell(let flags, let text, let colspan, let rowspan): - if boxed { - buffer.appendInt32(878078826) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 7) != 0 {text!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(colspan!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(rowspan!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pageTableCell(let flags, let text, let colspan, let rowspan): - return ("pageTableCell", [("flags", String(describing: flags)), ("text", String(describing: text)), ("colspan", String(describing: colspan)), ("rowspan", String(describing: rowspan))]) - } - } - - public static func parse_pageTableCell(_ reader: BufferReader) -> PageTableCell? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.RichText? - if Int(_1!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.RichText - } } - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - var _4: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 7) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PageTableCell.pageTableCell(flags: _1!, text: _2, colspan: _3, rowspan: _4) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PageTableRow: TypeConstructorDescription { - case pageTableRow(cells: [Api.PageTableCell]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pageTableRow(let cells): - if boxed { - buffer.appendInt32(-524237339) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(cells.count)) - for item in cells { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pageTableRow(let cells): - return ("pageTableRow", [("cells", String(describing: cells))]) - } - } - - public static func parse_pageTableRow(_ reader: BufferReader) -> PageTableRow? { - var _1: [Api.PageTableCell]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageTableCell.self) + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) } let _c1 = _1 != nil if _c1 { - return Api.PageTableRow.pageTableRow(cells: _1!) + return Api.PageListItem.pageListItemBlocks(blocks: _1!) } else { return nil } } - - } -} -public extension Api { - enum PasswordKdfAlgo: TypeConstructorDescription { - case passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: Buffer, salt2: Buffer, g: Int32, p: Buffer) - case passwordKdfAlgoUnknown - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(let salt1, let salt2, let g, let p): - if boxed { - buffer.appendInt32(982592842) - } - serializeBytes(salt1, buffer: buffer, boxed: false) - serializeBytes(salt2, buffer: buffer, boxed: false) - serializeInt32(g, buffer: buffer, boxed: false) - serializeBytes(p, buffer: buffer, boxed: false) - break - case .passwordKdfAlgoUnknown: - if boxed { - buffer.appendInt32(-732254058) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(let salt1, let salt2, let g, let p): - return ("passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow", [("salt1", String(describing: salt1)), ("salt2", String(describing: salt2)), ("g", String(describing: g)), ("p", String(describing: p))]) - case .passwordKdfAlgoUnknown: - return ("passwordKdfAlgoUnknown", []) - } - } - - public static func parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(_ reader: BufferReader) -> PasswordKdfAlgo? { - var _1: Buffer? - _1 = parseBytes(reader) - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Int32? - _3 = reader.readInt32() - var _4: Buffer? - _4 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: _1!, salt2: _2!, g: _3!, p: _4!) + public static func parse_pageListItemText(_ reader: BufferReader) -> PageListItem? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText } - else { - return nil - } - } - public static func parse_passwordKdfAlgoUnknown(_ reader: BufferReader) -> PasswordKdfAlgo? { - return Api.PasswordKdfAlgo.passwordKdfAlgoUnknown - } - - } -} -public extension Api { - enum PaymentCharge: TypeConstructorDescription { - case paymentCharge(id: String, providerChargeId: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentCharge(let id, let providerChargeId): - if boxed { - buffer.appendInt32(-368917890) - } - serializeString(id, buffer: buffer, boxed: false) - serializeString(providerChargeId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .paymentCharge(let id, let providerChargeId): - return ("paymentCharge", [("id", String(describing: id)), ("providerChargeId", String(describing: providerChargeId))]) - } - } - - public static func parse_paymentCharge(_ reader: BufferReader) -> PaymentCharge? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PaymentCharge.paymentCharge(id: _1!, providerChargeId: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PaymentRequestedInfo: TypeConstructorDescription { - case paymentRequestedInfo(flags: Int32, name: String?, phone: String?, email: String?, shippingAddress: Api.PostAddress?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentRequestedInfo(let flags, let name, let phone, let email, let shippingAddress): - if boxed { - buffer.appendInt32(-1868808300) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(name!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(phone!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(email!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {shippingAddress!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .paymentRequestedInfo(let flags, let name, let phone, let email, let shippingAddress): - return ("paymentRequestedInfo", [("flags", String(describing: flags)), ("name", String(describing: name)), ("phone", String(describing: phone)), ("email", String(describing: email)), ("shippingAddress", String(describing: shippingAddress))]) - } - } - - public static func parse_paymentRequestedInfo(_ reader: BufferReader) -> PaymentRequestedInfo? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } - var _3: String? - if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } - var _4: String? - if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) } - var _5: Api.PostAddress? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.PostAddress - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.PaymentRequestedInfo.paymentRequestedInfo(flags: _1!, name: _2, phone: _3, email: _4, shippingAddress: _5) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PaymentSavedCredentials: TypeConstructorDescription { - case paymentSavedCredentialsCard(id: String, title: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentSavedCredentialsCard(let id, let title): - if boxed { - buffer.appendInt32(-842892769) - } - serializeString(id, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .paymentSavedCredentialsCard(let id, let title): - return ("paymentSavedCredentialsCard", [("id", String(describing: id)), ("title", String(describing: title))]) - } - } - - public static func parse_paymentSavedCredentialsCard(_ reader: BufferReader) -> PaymentSavedCredentials? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PaymentSavedCredentials.paymentSavedCredentialsCard(id: _1!, title: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Peer: TypeConstructorDescription { - case peerChannel(channelId: Int64) - case peerChat(chatId: Int64) - case peerUser(userId: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerChannel(let channelId): - if boxed { - buffer.appendInt32(-1566230754) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - break - case .peerChat(let chatId): - if boxed { - buffer.appendInt32(918946202) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - break - case .peerUser(let userId): - if boxed { - buffer.appendInt32(1498486562) - } - serializeInt64(userId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerChannel(let channelId): - return ("peerChannel", [("channelId", String(describing: channelId))]) - case .peerChat(let chatId): - return ("peerChat", [("chatId", String(describing: chatId))]) - case .peerUser(let userId): - return ("peerUser", [("userId", String(describing: userId))]) - } - } - - public static func parse_peerChannel(_ reader: BufferReader) -> Peer? { - var _1: Int64? - _1 = reader.readInt64() let _c1 = _1 != nil if _c1 { - return Api.Peer.peerChannel(channelId: _1!) - } - else { - return nil - } - } - public static func parse_peerChat(_ reader: BufferReader) -> Peer? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Peer.peerChat(chatId: _1!) - } - else { - return nil - } - } - public static func parse_peerUser(_ reader: BufferReader) -> Peer? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Peer.peerUser(userId: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PeerBlocked: TypeConstructorDescription { - case peerBlocked(peerId: Api.Peer, date: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerBlocked(let peerId, let date): - if boxed { - buffer.appendInt32(-386039788) - } - peerId.serialize(buffer, true) - serializeInt32(date, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerBlocked(let peerId, let date): - return ("peerBlocked", [("peerId", String(describing: peerId)), ("date", String(describing: date))]) - } - } - - public static func parse_peerBlocked(_ reader: BufferReader) -> PeerBlocked? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PeerBlocked.peerBlocked(peerId: _1!, date: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PeerLocated: TypeConstructorDescription { - case peerLocated(peer: Api.Peer, expires: Int32, distance: Int32) - case peerSelfLocated(expires: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerLocated(let peer, let expires, let distance): - if boxed { - buffer.appendInt32(-901375139) - } - peer.serialize(buffer, true) - serializeInt32(expires, buffer: buffer, boxed: false) - serializeInt32(distance, buffer: buffer, boxed: false) - break - case .peerSelfLocated(let expires): - if boxed { - buffer.appendInt32(-118740917) - } - serializeInt32(expires, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerLocated(let peer, let expires, let distance): - return ("peerLocated", [("peer", String(describing: peer)), ("expires", String(describing: expires)), ("distance", String(describing: distance))]) - case .peerSelfLocated(let expires): - return ("peerSelfLocated", [("expires", String(describing: expires))]) - } - } - - public static func parse_peerLocated(_ reader: BufferReader) -> PeerLocated? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.PeerLocated.peerLocated(peer: _1!, expires: _2!, distance: _3!) - } - else { - return nil - } - } - public static func parse_peerSelfLocated(_ reader: BufferReader) -> PeerLocated? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.PeerLocated.peerSelfLocated(expires: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PeerNotifySettings: TypeConstructorDescription { - case peerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, iosSound: Api.NotificationSound?, androidSound: Api.NotificationSound?, otherSound: Api.NotificationSound?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound): - if boxed { - buffer.appendInt32(-1472527322) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {iosSound!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {androidSound!.serialize(buffer, true)} - if Int(flags) & Int(1 << 5) != 0 {otherSound!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound): - return ("peerNotifySettings", [("flags", String(describing: flags)), ("showPreviews", String(describing: showPreviews)), ("silent", String(describing: silent)), ("muteUntil", String(describing: muteUntil)), ("iosSound", String(describing: iosSound)), ("androidSound", String(describing: androidSound)), ("otherSound", String(describing: otherSound))]) - } - } - - public static func parse_peerNotifySettings(_ reader: BufferReader) -> PeerNotifySettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.Bool? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Bool - } } - var _3: Api.Bool? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Bool - } } - var _4: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } - var _5: Api.NotificationSound? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.NotificationSound - } } - var _6: Api.NotificationSound? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.NotificationSound - } } - var _7: Api.NotificationSound? - if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.NotificationSound - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 5) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.PeerNotifySettings.peerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, iosSound: _5, androidSound: _6, otherSound: _7) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PeerSettings: TypeConstructorDescription { - case peerSettings(flags: Int32, geoDistance: Int32?, requestChatTitle: String?, requestChatDate: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerSettings(let flags, let geoDistance, let requestChatTitle, let requestChatDate): - if boxed { - buffer.appendInt32(-1525149427) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(geoDistance!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 9) != 0 {serializeString(requestChatTitle!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 9) != 0 {serializeInt32(requestChatDate!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerSettings(let flags, let geoDistance, let requestChatTitle, let requestChatDate): - return ("peerSettings", [("flags", String(describing: flags)), ("geoDistance", String(describing: geoDistance)), ("requestChatTitle", String(describing: requestChatTitle)), ("requestChatDate", String(describing: requestChatDate))]) - } - } - - public static func parse_peerSettings(_ reader: BufferReader) -> PeerSettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_2 = reader.readInt32() } - var _3: String? - if Int(_1!) & Int(1 << 9) != 0 {_3 = parseString(reader) } - var _4: Int32? - if Int(_1!) & Int(1 << 9) != 0 {_4 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 6) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 9) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PeerSettings.peerSettings(flags: _1!, geoDistance: _2, requestChatTitle: _3, requestChatDate: _4) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PhoneCall: TypeConstructorDescription { - case phoneCall(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAOrB: Buffer, keyFingerprint: Int64, protocol: Api.PhoneCallProtocol, connections: [Api.PhoneConnection], startDate: Int32) - case phoneCallAccepted(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gB: Buffer, protocol: Api.PhoneCallProtocol) - case phoneCallDiscarded(flags: Int32, id: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) - case phoneCallEmpty(id: Int64) - case phoneCallRequested(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAHash: Buffer, protocol: Api.PhoneCallProtocol) - case phoneCallWaiting(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, protocol: Api.PhoneCallProtocol, receiveDate: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneCall(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAOrB, let keyFingerprint, let `protocol`, let connections, let startDate): - if boxed { - buffer.appendInt32(-1770029977) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(adminId, buffer: buffer, boxed: false) - serializeInt64(participantId, buffer: buffer, boxed: false) - serializeBytes(gAOrB, buffer: buffer, boxed: false) - serializeInt64(keyFingerprint, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(connections.count)) - for item in connections { - item.serialize(buffer, true) - } - serializeInt32(startDate, buffer: buffer, boxed: false) - break - case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`): - if boxed { - buffer.appendInt32(912311057) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(adminId, buffer: buffer, boxed: false) - serializeInt64(participantId, buffer: buffer, boxed: false) - serializeBytes(gB, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - break - case .phoneCallDiscarded(let flags, let id, let reason, let duration): - if boxed { - buffer.appendInt32(1355435489) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} - break - case .phoneCallEmpty(let id): - if boxed { - buffer.appendInt32(1399245077) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`): - if boxed { - buffer.appendInt32(347139340) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(adminId, buffer: buffer, boxed: false) - serializeInt64(participantId, buffer: buffer, boxed: false) - serializeBytes(gAHash, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - break - case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate): - if boxed { - buffer.appendInt32(-987599081) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(adminId, buffer: buffer, boxed: false) - serializeInt64(participantId, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(receiveDate!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneCall(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAOrB, let keyFingerprint, let `protocol`, let connections, let startDate): - return ("phoneCall", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gAOrB", String(describing: gAOrB)), ("keyFingerprint", String(describing: keyFingerprint)), ("`protocol`", String(describing: `protocol`)), ("connections", String(describing: connections)), ("startDate", String(describing: startDate))]) - case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`): - return ("phoneCallAccepted", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gB", String(describing: gB)), ("`protocol`", String(describing: `protocol`))]) - case .phoneCallDiscarded(let flags, let id, let reason, let duration): - return ("phoneCallDiscarded", [("flags", String(describing: flags)), ("id", String(describing: id)), ("reason", String(describing: reason)), ("duration", String(describing: duration))]) - case .phoneCallEmpty(let id): - return ("phoneCallEmpty", [("id", String(describing: id))]) - case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`): - return ("phoneCallRequested", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]) - case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate): - return ("phoneCallWaiting", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("`protocol`", String(describing: `protocol`)), ("receiveDate", String(describing: receiveDate))]) - } - } - - public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int64? - _5 = reader.readInt64() - var _6: Int64? - _6 = reader.readInt64() - var _7: Buffer? - _7 = parseBytes(reader) - var _8: Int64? - _8 = reader.readInt64() - var _9: Api.PhoneCallProtocol? - if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol - } - var _10: [Api.PhoneConnection]? - if let _ = reader.readInt32() { - _10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhoneConnection.self) - } - var _11: Int32? - _11 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = _10 != nil - let _c11 = _11 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 { - return Api.PhoneCall.phoneCall(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAOrB: _7!, keyFingerprint: _8!, protocol: _9!, connections: _10!, startDate: _11!) - } - else { - return nil - } - } - public static func parse_phoneCallAccepted(_ reader: BufferReader) -> PhoneCall? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int64? - _5 = reader.readInt64() - var _6: Int64? - _6 = reader.readInt64() - var _7: Buffer? - _7 = parseBytes(reader) - var _8: Api.PhoneCallProtocol? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.PhoneCall.phoneCallAccepted(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gB: _7!, protocol: _8!) - } - else { - return nil - } - } - public static func parse_phoneCallDiscarded(_ reader: BufferReader) -> PhoneCall? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.PhoneCallDiscardReason? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.PhoneCallDiscardReason - } } - var _4: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PhoneCall.phoneCallDiscarded(flags: _1!, id: _2!, reason: _3, duration: _4) - } - else { - return nil - } - } - public static func parse_phoneCallEmpty(_ reader: BufferReader) -> PhoneCall? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.PhoneCall.phoneCallEmpty(id: _1!) - } - else { - return nil - } - } - public static func parse_phoneCallRequested(_ reader: BufferReader) -> PhoneCall? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int64? - _5 = reader.readInt64() - var _6: Int64? - _6 = reader.readInt64() - var _7: Buffer? - _7 = parseBytes(reader) - var _8: Api.PhoneCallProtocol? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.PhoneCall.phoneCallRequested(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAHash: _7!, protocol: _8!) - } - else { - return nil - } - } - public static func parse_phoneCallWaiting(_ reader: BufferReader) -> PhoneCall? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int64? - _5 = reader.readInt64() - var _6: Int64? - _6 = reader.readInt64() - var _7: Api.PhoneCallProtocol? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol - } - var _8: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_8 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = (Int(_1!) & Int(1 << 0) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.PhoneCall.phoneCallWaiting(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, protocol: _7!, receiveDate: _8) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PhoneCallDiscardReason: TypeConstructorDescription { - case phoneCallDiscardReasonBusy - case phoneCallDiscardReasonDisconnect - case phoneCallDiscardReasonHangup - case phoneCallDiscardReasonMissed - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneCallDiscardReasonBusy: - if boxed { - buffer.appendInt32(-84416311) - } - - break - case .phoneCallDiscardReasonDisconnect: - if boxed { - buffer.appendInt32(-527056480) - } - - break - case .phoneCallDiscardReasonHangup: - if boxed { - buffer.appendInt32(1471006352) - } - - break - case .phoneCallDiscardReasonMissed: - if boxed { - buffer.appendInt32(-2048646399) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneCallDiscardReasonBusy: - return ("phoneCallDiscardReasonBusy", []) - case .phoneCallDiscardReasonDisconnect: - return ("phoneCallDiscardReasonDisconnect", []) - case .phoneCallDiscardReasonHangup: - return ("phoneCallDiscardReasonHangup", []) - case .phoneCallDiscardReasonMissed: - return ("phoneCallDiscardReasonMissed", []) - } - } - - public static func parse_phoneCallDiscardReasonBusy(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonBusy - } - public static func parse_phoneCallDiscardReasonDisconnect(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonDisconnect - } - public static func parse_phoneCallDiscardReasonHangup(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonHangup - } - public static func parse_phoneCallDiscardReasonMissed(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonMissed - } - - } -} -public extension Api { - enum PhoneCallProtocol: TypeConstructorDescription { - case phoneCallProtocol(flags: Int32, minLayer: Int32, maxLayer: Int32, libraryVersions: [String]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneCallProtocol(let flags, let minLayer, let maxLayer, let libraryVersions): - if boxed { - buffer.appendInt32(-58224696) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(minLayer, buffer: buffer, boxed: false) - serializeInt32(maxLayer, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(libraryVersions.count)) - for item in libraryVersions { - serializeString(item, buffer: buffer, boxed: false) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneCallProtocol(let flags, let minLayer, let maxLayer, let libraryVersions): - return ("phoneCallProtocol", [("flags", String(describing: flags)), ("minLayer", String(describing: minLayer)), ("maxLayer", String(describing: maxLayer)), ("libraryVersions", String(describing: libraryVersions))]) - } - } - - public static func parse_phoneCallProtocol(_ reader: BufferReader) -> PhoneCallProtocol? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: [String]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PhoneCallProtocol.phoneCallProtocol(flags: _1!, minLayer: _2!, maxLayer: _3!, libraryVersions: _4!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PhoneConnection: TypeConstructorDescription { - case phoneConnection(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, peerTag: Buffer) - case phoneConnectionWebrtc(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, username: String, password: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag): - if boxed { - buffer.appendInt32(-1665063993) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeString(ip, buffer: buffer, boxed: false) - serializeString(ipv6, buffer: buffer, boxed: false) - serializeInt32(port, buffer: buffer, boxed: false) - serializeBytes(peerTag, buffer: buffer, boxed: false) - break - case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password): - if boxed { - buffer.appendInt32(1667228533) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeString(ip, buffer: buffer, boxed: false) - serializeString(ipv6, buffer: buffer, boxed: false) - serializeInt32(port, buffer: buffer, boxed: false) - serializeString(username, buffer: buffer, boxed: false) - serializeString(password, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag): - return ("phoneConnection", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("peerTag", String(describing: peerTag))]) - case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password): - return ("phoneConnectionWebrtc", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("username", String(describing: username)), ("password", String(describing: password))]) - } - } - - public static func parse_phoneConnection(_ reader: BufferReader) -> PhoneConnection? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: Int32? - _5 = reader.readInt32() - var _6: Buffer? - _6 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.PhoneConnection.phoneConnection(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, peerTag: _6!) - } - else { - return nil - } - } - public static func parse_phoneConnectionWebrtc(_ reader: BufferReader) -> PhoneConnection? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: Int32? - _5 = reader.readInt32() - var _6: String? - _6 = parseString(reader) - var _7: String? - _7 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.PhoneConnection.phoneConnectionWebrtc(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, username: _6!, password: _7!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Photo: TypeConstructorDescription { - case photo(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, sizes: [Api.PhotoSize], videoSizes: [Api.VideoSize]?, dcId: Int32) - case photoEmpty(id: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let videoSizes, let dcId): - if boxed { - buffer.appendInt32(-82216347) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeBytes(fileReference, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sizes.count)) - for item in sizes { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(videoSizes!.count)) - for item in videoSizes! { - item.serialize(buffer, true) - }} - serializeInt32(dcId, buffer: buffer, boxed: false) - break - case .photoEmpty(let id): - if boxed { - buffer.appendInt32(590459437) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let videoSizes, let dcId): - return ("photo", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("fileReference", String(describing: fileReference)), ("date", String(describing: date)), ("sizes", String(describing: sizes)), ("videoSizes", String(describing: videoSizes)), ("dcId", String(describing: dcId))]) - case .photoEmpty(let id): - return ("photoEmpty", [("id", String(describing: id))]) - } - } - - public static func parse_photo(_ reader: BufferReader) -> Photo? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Buffer? - _4 = parseBytes(reader) - var _5: Int32? - _5 = reader.readInt32() - var _6: [Api.PhotoSize]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self) - } - var _7: [Api.VideoSize]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.VideoSize.self) - } } - var _8: Int32? - _8 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.Photo.photo(flags: _1!, id: _2!, accessHash: _3!, fileReference: _4!, date: _5!, sizes: _6!, videoSizes: _7, dcId: _8!) - } - else { - return nil - } - } - public static func parse_photoEmpty(_ reader: BufferReader) -> Photo? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Photo.photoEmpty(id: _1!) + return Api.PageListItem.pageListItemText(text: _1!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api15.swift b/submodules/TelegramApi/Sources/Api15.swift index b09a1ee009..b797c99619 100644 --- a/submodules/TelegramApi/Sources/Api15.swift +++ b/submodules/TelegramApi/Sources/Api15.swift @@ -1,90 +1,270 @@ public extension Api { - enum PhotoSize: TypeConstructorDescription { - case photoCachedSize(type: String, w: Int32, h: Int32, bytes: Buffer) - case photoPathSize(type: String, bytes: Buffer) - case photoSize(type: String, w: Int32, h: Int32, size: Int32) - case photoSizeEmpty(type: String) - case photoSizeProgressive(type: String, w: Int32, h: Int32, sizes: [Int32]) - case photoStrippedSize(type: String, bytes: Buffer) + enum PageListOrderedItem: TypeConstructorDescription { + case pageListOrderedItemBlocks(num: String, blocks: [Api.PageBlock]) + case pageListOrderedItemText(num: String, text: Api.RichText) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .photoCachedSize(let type, let w, let h, let bytes): + case .pageListOrderedItemBlocks(let num, let blocks): if boxed { - buffer.appendInt32(35527382) + buffer.appendInt32(-1730311882) } - serializeString(type, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) - break - case .photoPathSize(let type, let bytes): - if boxed { - buffer.appendInt32(-668906175) - } - serializeString(type, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) - break - case .photoSize(let type, let w, let h, let size): - if boxed { - buffer.appendInt32(1976012384) - } - serializeString(type, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) - serializeInt32(size, buffer: buffer, boxed: false) - break - case .photoSizeEmpty(let type): - if boxed { - buffer.appendInt32(236446268) - } - serializeString(type, buffer: buffer, boxed: false) - break - case .photoSizeProgressive(let type, let w, let h, let sizes): - if boxed { - buffer.appendInt32(-96535659) - } - serializeString(type, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) + serializeString(num, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sizes.count)) - for item in sizes { - serializeInt32(item, buffer: buffer, boxed: false) + buffer.appendInt32(Int32(blocks.count)) + for item in blocks { + item.serialize(buffer, true) } break - case .photoStrippedSize(let type, let bytes): + case .pageListOrderedItemText(let num, let text): if boxed { - buffer.appendInt32(-525288402) + buffer.appendInt32(1577484359) } - serializeString(type, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) + serializeString(num, buffer: buffer, boxed: false) + text.serialize(buffer, true) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .photoCachedSize(let type, let w, let h, let bytes): - return ("photoCachedSize", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("bytes", String(describing: bytes))]) - case .photoPathSize(let type, let bytes): - return ("photoPathSize", [("type", String(describing: type)), ("bytes", String(describing: bytes))]) - case .photoSize(let type, let w, let h, let size): - return ("photoSize", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("size", String(describing: size))]) - case .photoSizeEmpty(let type): - return ("photoSizeEmpty", [("type", String(describing: type))]) - case .photoSizeProgressive(let type, let w, let h, let sizes): - return ("photoSizeProgressive", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("sizes", String(describing: sizes))]) - case .photoStrippedSize(let type, let bytes): - return ("photoStrippedSize", [("type", String(describing: type)), ("bytes", String(describing: bytes))]) + case .pageListOrderedItemBlocks(let num, let blocks): + return ("pageListOrderedItemBlocks", [("num", String(describing: num)), ("blocks", String(describing: blocks))]) + case .pageListOrderedItemText(let num, let text): + return ("pageListOrderedItemText", [("num", String(describing: num)), ("text", String(describing: text))]) } } - public static func parse_photoCachedSize(_ reader: BufferReader) -> PhotoSize? { + public static func parse_pageListOrderedItemBlocks(_ reader: BufferReader) -> PageListOrderedItem? { var _1: String? _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() + var _2: [Api.PageBlock]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageListOrderedItem.pageListOrderedItemBlocks(num: _1!, blocks: _2!) + } + else { + return nil + } + } + public static func parse_pageListOrderedItemText(_ reader: BufferReader) -> PageListOrderedItem? { + var _1: String? + _1 = parseString(reader) + var _2: Api.RichText? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PageListOrderedItem.pageListOrderedItemText(num: _1!, text: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PageRelatedArticle: TypeConstructorDescription { + case pageRelatedArticle(flags: Int32, url: String, webpageId: Int64, title: String?, description: String?, photoId: Int64?, author: String?, publishedDate: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate): + if boxed { + buffer.appendInt32(-1282352120) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(webpageId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(description!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt64(photoId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(author!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(publishedDate!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pageRelatedArticle(let flags, let url, let webpageId, let title, let description, let photoId, let author, let publishedDate): + return ("pageRelatedArticle", [("flags", String(describing: flags)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photoId", String(describing: photoId)), ("author", String(describing: author)), ("publishedDate", String(describing: publishedDate))]) + } + } + + public static func parse_pageRelatedArticle(_ reader: BufferReader) -> PageRelatedArticle? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } + var _5: String? + if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) } + var _6: Int64? + if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt64() } + var _7: String? + if Int(_1!) & Int(1 << 3) != 0 {_7 = parseString(reader) } + var _8: Int32? + if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.PageRelatedArticle.pageRelatedArticle(flags: _1!, url: _2!, webpageId: _3!, title: _4, description: _5, photoId: _6, author: _7, publishedDate: _8) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PageTableCell: TypeConstructorDescription { + case pageTableCell(flags: Int32, text: Api.RichText?, colspan: Int32?, rowspan: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageTableCell(let flags, let text, let colspan, let rowspan): + if boxed { + buffer.appendInt32(878078826) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 7) != 0 {text!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(colspan!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(rowspan!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pageTableCell(let flags, let text, let colspan, let rowspan): + return ("pageTableCell", [("flags", String(describing: flags)), ("text", String(describing: text)), ("colspan", String(describing: colspan)), ("rowspan", String(describing: rowspan))]) + } + } + + public static func parse_pageTableCell(_ reader: BufferReader) -> PageTableCell? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.RichText? + if Int(_1!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.RichText + } } + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + var _4: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 7) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PageTableCell.pageTableCell(flags: _1!, text: _2, colspan: _3, rowspan: _4) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PageTableRow: TypeConstructorDescription { + case pageTableRow(cells: [Api.PageTableCell]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pageTableRow(let cells): + if boxed { + buffer.appendInt32(-524237339) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(cells.count)) + for item in cells { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pageTableRow(let cells): + return ("pageTableRow", [("cells", String(describing: cells))]) + } + } + + public static func parse_pageTableRow(_ reader: BufferReader) -> PageTableRow? { + var _1: [Api.PageTableCell]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageTableCell.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PageTableRow.pageTableRow(cells: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PasswordKdfAlgo: TypeConstructorDescription { + case passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: Buffer, salt2: Buffer, g: Int32, p: Buffer) + case passwordKdfAlgoUnknown + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(let salt1, let salt2, let g, let p): + if boxed { + buffer.appendInt32(982592842) + } + serializeBytes(salt1, buffer: buffer, boxed: false) + serializeBytes(salt2, buffer: buffer, boxed: false) + serializeInt32(g, buffer: buffer, boxed: false) + serializeBytes(p, buffer: buffer, boxed: false) + break + case .passwordKdfAlgoUnknown: + if boxed { + buffer.appendInt32(-732254058) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(let salt1, let salt2, let g, let p): + return ("passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow", [("salt1", String(describing: salt1)), ("salt2", String(describing: salt2)), ("g", String(describing: g)), ("p", String(describing: p))]) + case .passwordKdfAlgoUnknown: + return ("passwordKdfAlgoUnknown", []) + } + } + + public static func parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(_ reader: BufferReader) -> PasswordKdfAlgo? { + var _1: Buffer? + _1 = parseBytes(reader) + var _2: Buffer? + _2 = parseBytes(reader) var _3: Int32? _3 = reader.readInt32() var _4: Buffer? @@ -94,768 +274,50 @@ public extension Api { let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.PhotoSize.photoCachedSize(type: _1!, w: _2!, h: _3!, bytes: _4!) + return Api.PasswordKdfAlgo.passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: _1!, salt2: _2!, g: _3!, p: _4!) } else { return nil } } - public static func parse_photoPathSize(_ reader: BufferReader) -> PhotoSize? { - var _1: String? - _1 = parseString(reader) - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PhotoSize.photoPathSize(type: _1!, bytes: _2!) - } - else { - return nil - } - } - public static func parse_photoSize(_ reader: BufferReader) -> PhotoSize? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PhotoSize.photoSize(type: _1!, w: _2!, h: _3!, size: _4!) - } - else { - return nil - } - } - public static func parse_photoSizeEmpty(_ reader: BufferReader) -> PhotoSize? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.PhotoSize.photoSizeEmpty(type: _1!) - } - else { - return nil - } - } - public static func parse_photoSizeProgressive(_ reader: BufferReader) -> PhotoSize? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: [Int32]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.PhotoSize.photoSizeProgressive(type: _1!, w: _2!, h: _3!, sizes: _4!) - } - else { - return nil - } - } - public static func parse_photoStrippedSize(_ reader: BufferReader) -> PhotoSize? { - var _1: String? - _1 = parseString(reader) - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PhotoSize.photoStrippedSize(type: _1!, bytes: _2!) - } - else { - return nil - } + public static func parse_passwordKdfAlgoUnknown(_ reader: BufferReader) -> PasswordKdfAlgo? { + return Api.PasswordKdfAlgo.passwordKdfAlgoUnknown } } } public extension Api { - enum Poll: TypeConstructorDescription { - case poll(id: Int64, flags: Int32, question: String, answers: [Api.PollAnswer], closePeriod: Int32?, closeDate: Int32?) + enum PaymentCharge: TypeConstructorDescription { + case paymentCharge(id: String, providerChargeId: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .poll(let id, let flags, let question, let answers, let closePeriod, let closeDate): + case .paymentCharge(let id, let providerChargeId): if boxed { - buffer.appendInt32(-2032041631) + buffer.appendInt32(-368917890) } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(question, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(answers.count)) - for item in answers { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(closePeriod!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {serializeInt32(closeDate!, buffer: buffer, boxed: false)} + serializeString(id, buffer: buffer, boxed: false) + serializeString(providerChargeId, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .poll(let id, let flags, let question, let answers, let closePeriod, let closeDate): - return ("poll", [("id", String(describing: id)), ("flags", String(describing: flags)), ("question", String(describing: question)), ("answers", String(describing: answers)), ("closePeriod", String(describing: closePeriod)), ("closeDate", String(describing: closeDate))]) + case .paymentCharge(let id, let providerChargeId): + return ("paymentCharge", [("id", String(describing: id)), ("providerChargeId", String(describing: providerChargeId))]) } } - public static func parse_poll(_ reader: BufferReader) -> Poll? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: [Api.PollAnswer]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PollAnswer.self) - } - var _5: Int32? - if Int(_2!) & Int(1 << 4) != 0 {_5 = reader.readInt32() } - var _6: Int32? - if Int(_2!) & Int(1 << 5) != 0 {_6 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_2!) & Int(1 << 4) == 0) || _5 != nil - let _c6 = (Int(_2!) & Int(1 << 5) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Poll.poll(id: _1!, flags: _2!, question: _3!, answers: _4!, closePeriod: _5, closeDate: _6) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PollAnswer: TypeConstructorDescription { - case pollAnswer(text: String, option: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pollAnswer(let text, let option): - if boxed { - buffer.appendInt32(1823064809) - } - serializeString(text, buffer: buffer, boxed: false) - serializeBytes(option, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pollAnswer(let text, let option): - return ("pollAnswer", [("text", String(describing: text)), ("option", String(describing: option))]) - } - } - - public static func parse_pollAnswer(_ reader: BufferReader) -> PollAnswer? { - var _1: String? - _1 = parseString(reader) - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PollAnswer.pollAnswer(text: _1!, option: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PollAnswerVoters: TypeConstructorDescription { - case pollAnswerVoters(flags: Int32, option: Buffer, voters: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pollAnswerVoters(let flags, let option, let voters): - if boxed { - buffer.appendInt32(997055186) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeBytes(option, buffer: buffer, boxed: false) - serializeInt32(voters, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pollAnswerVoters(let flags, let option, let voters): - return ("pollAnswerVoters", [("flags", String(describing: flags)), ("option", String(describing: option)), ("voters", String(describing: voters))]) - } - } - - public static func parse_pollAnswerVoters(_ reader: BufferReader) -> PollAnswerVoters? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.PollAnswerVoters.pollAnswerVoters(flags: _1!, option: _2!, voters: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PollResults: TypeConstructorDescription { - case pollResults(flags: Int32, results: [Api.PollAnswerVoters]?, totalVoters: Int32?, recentVoters: [Int64]?, solution: String?, solutionEntities: [Api.MessageEntity]?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .pollResults(let flags, let results, let totalVoters, let recentVoters, let solution, let solutionEntities): - if boxed { - buffer.appendInt32(-591909213) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(results!.count)) - for item in results! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(totalVoters!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(recentVoters!.count)) - for item in recentVoters! { - serializeInt64(item, buffer: buffer, boxed: false) - }} - if Int(flags) & Int(1 << 4) != 0 {serializeString(solution!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(solutionEntities!.count)) - for item in solutionEntities! { - item.serialize(buffer, true) - }} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .pollResults(let flags, let results, let totalVoters, let recentVoters, let solution, let solutionEntities): - return ("pollResults", [("flags", String(describing: flags)), ("results", String(describing: results)), ("totalVoters", String(describing: totalVoters)), ("recentVoters", String(describing: recentVoters)), ("solution", String(describing: solution)), ("solutionEntities", String(describing: solutionEntities))]) - } - } - - public static func parse_pollResults(_ reader: BufferReader) -> PollResults? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.PollAnswerVoters]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PollAnswerVoters.self) - } } - var _3: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } - var _4: [Int64]? - if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } } - var _5: String? - if Int(_1!) & Int(1 << 4) != 0 {_5 = parseString(reader) } - var _6: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.PollResults.pollResults(flags: _1!, results: _2, totalVoters: _3, recentVoters: _4, solution: _5, solutionEntities: _6) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PopularContact: TypeConstructorDescription { - case popularContact(clientId: Int64, importers: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .popularContact(let clientId, let importers): - if boxed { - buffer.appendInt32(1558266229) - } - serializeInt64(clientId, buffer: buffer, boxed: false) - serializeInt32(importers, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .popularContact(let clientId, let importers): - return ("popularContact", [("clientId", String(describing: clientId)), ("importers", String(describing: importers))]) - } - } - - public static func parse_popularContact(_ reader: BufferReader) -> PopularContact? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.PopularContact.popularContact(clientId: _1!, importers: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PostAddress: TypeConstructorDescription { - case postAddress(streetLine1: String, streetLine2: String, city: String, state: String, countryIso2: String, postCode: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .postAddress(let streetLine1, let streetLine2, let city, let state, let countryIso2, let postCode): - if boxed { - buffer.appendInt32(512535275) - } - serializeString(streetLine1, buffer: buffer, boxed: false) - serializeString(streetLine2, buffer: buffer, boxed: false) - serializeString(city, buffer: buffer, boxed: false) - serializeString(state, buffer: buffer, boxed: false) - serializeString(countryIso2, buffer: buffer, boxed: false) - serializeString(postCode, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .postAddress(let streetLine1, let streetLine2, let city, let state, let countryIso2, let postCode): - return ("postAddress", [("streetLine1", String(describing: streetLine1)), ("streetLine2", String(describing: streetLine2)), ("city", String(describing: city)), ("state", String(describing: state)), ("countryIso2", String(describing: countryIso2)), ("postCode", String(describing: postCode))]) - } - } - - public static func parse_postAddress(_ reader: BufferReader) -> PostAddress? { + public static func parse_paymentCharge(_ reader: BufferReader) -> PaymentCharge? { var _1: String? _1 = parseString(reader) var _2: String? _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: String? - _6 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.PostAddress.postAddress(streetLine1: _1!, streetLine2: _2!, city: _3!, state: _4!, countryIso2: _5!, postCode: _6!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum PrivacyKey: TypeConstructorDescription { - case privacyKeyAddedByPhone - case privacyKeyChatInvite - case privacyKeyForwards - case privacyKeyPhoneCall - case privacyKeyPhoneNumber - case privacyKeyPhoneP2P - case privacyKeyProfilePhoto - case privacyKeyStatusTimestamp - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .privacyKeyAddedByPhone: - if boxed { - buffer.appendInt32(1124062251) - } - - break - case .privacyKeyChatInvite: - if boxed { - buffer.appendInt32(1343122938) - } - - break - case .privacyKeyForwards: - if boxed { - buffer.appendInt32(1777096355) - } - - break - case .privacyKeyPhoneCall: - if boxed { - buffer.appendInt32(1030105979) - } - - break - case .privacyKeyPhoneNumber: - if boxed { - buffer.appendInt32(-778378131) - } - - break - case .privacyKeyPhoneP2P: - if boxed { - buffer.appendInt32(961092808) - } - - break - case .privacyKeyProfilePhoto: - if boxed { - buffer.appendInt32(-1777000467) - } - - break - case .privacyKeyStatusTimestamp: - if boxed { - buffer.appendInt32(-1137792208) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .privacyKeyAddedByPhone: - return ("privacyKeyAddedByPhone", []) - case .privacyKeyChatInvite: - return ("privacyKeyChatInvite", []) - case .privacyKeyForwards: - return ("privacyKeyForwards", []) - case .privacyKeyPhoneCall: - return ("privacyKeyPhoneCall", []) - case .privacyKeyPhoneNumber: - return ("privacyKeyPhoneNumber", []) - case .privacyKeyPhoneP2P: - return ("privacyKeyPhoneP2P", []) - case .privacyKeyProfilePhoto: - return ("privacyKeyProfilePhoto", []) - case .privacyKeyStatusTimestamp: - return ("privacyKeyStatusTimestamp", []) - } - } - - public static func parse_privacyKeyAddedByPhone(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyAddedByPhone - } - public static func parse_privacyKeyChatInvite(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyChatInvite - } - public static func parse_privacyKeyForwards(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyForwards - } - public static func parse_privacyKeyPhoneCall(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyPhoneCall - } - public static func parse_privacyKeyPhoneNumber(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyPhoneNumber - } - public static func parse_privacyKeyPhoneP2P(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyPhoneP2P - } - public static func parse_privacyKeyProfilePhoto(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyProfilePhoto - } - public static func parse_privacyKeyStatusTimestamp(_ reader: BufferReader) -> PrivacyKey? { - return Api.PrivacyKey.privacyKeyStatusTimestamp - } - - } -} -public extension Api { - enum PrivacyRule: TypeConstructorDescription { - case privacyValueAllowAll - case privacyValueAllowChatParticipants(chats: [Int64]) - case privacyValueAllowContacts - case privacyValueAllowUsers(users: [Int64]) - case privacyValueDisallowAll - case privacyValueDisallowChatParticipants(chats: [Int64]) - case privacyValueDisallowContacts - case privacyValueDisallowUsers(users: [Int64]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .privacyValueAllowAll: - if boxed { - buffer.appendInt32(1698855810) - } - - break - case .privacyValueAllowChatParticipants(let chats): - if boxed { - buffer.appendInt32(1796427406) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .privacyValueAllowContacts: - if boxed { - buffer.appendInt32(-123988) - } - - break - case .privacyValueAllowUsers(let users): - if boxed { - buffer.appendInt32(-1198497870) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .privacyValueDisallowAll: - if boxed { - buffer.appendInt32(-1955338397) - } - - break - case .privacyValueDisallowChatParticipants(let chats): - if boxed { - buffer.appendInt32(1103656293) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .privacyValueDisallowContacts: - if boxed { - buffer.appendInt32(-125240806) - } - - break - case .privacyValueDisallowUsers(let users): - if boxed { - buffer.appendInt32(-463335103) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .privacyValueAllowAll: - return ("privacyValueAllowAll", []) - case .privacyValueAllowChatParticipants(let chats): - return ("privacyValueAllowChatParticipants", [("chats", String(describing: chats))]) - case .privacyValueAllowContacts: - return ("privacyValueAllowContacts", []) - case .privacyValueAllowUsers(let users): - return ("privacyValueAllowUsers", [("users", String(describing: users))]) - case .privacyValueDisallowAll: - return ("privacyValueDisallowAll", []) - case .privacyValueDisallowChatParticipants(let chats): - return ("privacyValueDisallowChatParticipants", [("chats", String(describing: chats))]) - case .privacyValueDisallowContacts: - return ("privacyValueDisallowContacts", []) - case .privacyValueDisallowUsers(let users): - return ("privacyValueDisallowUsers", [("users", String(describing: users))]) - } - } - - public static func parse_privacyValueAllowAll(_ reader: BufferReader) -> PrivacyRule? { - return Api.PrivacyRule.privacyValueAllowAll - } - public static func parse_privacyValueAllowChatParticipants(_ reader: BufferReader) -> PrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PrivacyRule.privacyValueAllowChatParticipants(chats: _1!) - } - else { - return nil - } - } - public static func parse_privacyValueAllowContacts(_ reader: BufferReader) -> PrivacyRule? { - return Api.PrivacyRule.privacyValueAllowContacts - } - public static func parse_privacyValueAllowUsers(_ reader: BufferReader) -> PrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PrivacyRule.privacyValueAllowUsers(users: _1!) - } - else { - return nil - } - } - public static func parse_privacyValueDisallowAll(_ reader: BufferReader) -> PrivacyRule? { - return Api.PrivacyRule.privacyValueDisallowAll - } - public static func parse_privacyValueDisallowChatParticipants(_ reader: BufferReader) -> PrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PrivacyRule.privacyValueDisallowChatParticipants(chats: _1!) - } - else { - return nil - } - } - public static func parse_privacyValueDisallowContacts(_ reader: BufferReader) -> PrivacyRule? { - return Api.PrivacyRule.privacyValueDisallowContacts - } - public static func parse_privacyValueDisallowUsers(_ reader: BufferReader) -> PrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.PrivacyRule.privacyValueDisallowUsers(users: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum ReactionCount: TypeConstructorDescription { - case reactionCount(flags: Int32, reaction: String, count: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .reactionCount(let flags, let reaction, let count): - if boxed { - buffer.appendInt32(1873957073) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(reaction, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .reactionCount(let flags, let reaction, let count): - return ("reactionCount", [("flags", String(describing: flags)), ("reaction", String(describing: reaction)), ("count", String(describing: count))]) - } - } - - public static func parse_reactionCount(_ reader: BufferReader) -> ReactionCount? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.ReactionCount.reactionCount(flags: _1!, reaction: _2!, count: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum ReceivedNotifyMessage: TypeConstructorDescription { - case receivedNotifyMessage(id: Int32, flags: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .receivedNotifyMessage(let id, let flags): - if boxed { - buffer.appendInt32(-1551583367) - } - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt32(flags, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .receivedNotifyMessage(let id, let flags): - return ("receivedNotifyMessage", [("id", String(describing: id)), ("flags", String(describing: flags))]) - } - } - - public static func parse_receivedNotifyMessage(_ reader: BufferReader) -> ReceivedNotifyMessage? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.ReceivedNotifyMessage.receivedNotifyMessage(id: _1!, flags: _2!) + return Api.PaymentCharge.paymentCharge(id: _1!, providerChargeId: _2!) } else { return nil @@ -865,47 +327,163 @@ public extension Api { } } public extension Api { - enum RecentMeUrl: TypeConstructorDescription { - case recentMeUrlChat(url: String, chatId: Int64) - case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite) - case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered) - case recentMeUrlUnknown(url: String) - case recentMeUrlUser(url: String, userId: Int64) + enum PaymentFormMethod: TypeConstructorDescription { + case paymentFormMethod(url: String, title: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .recentMeUrlChat(let url, let chatId): + case .paymentFormMethod(let url, let title): if boxed { - buffer.appendInt32(-1294306862) + buffer.appendInt32(-1996951013) } serializeString(url, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paymentFormMethod(let url, let title): + return ("paymentFormMethod", [("url", String(describing: url)), ("title", String(describing: title))]) + } + } + + public static func parse_paymentFormMethod(_ reader: BufferReader) -> PaymentFormMethod? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PaymentFormMethod.paymentFormMethod(url: _1!, title: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PaymentRequestedInfo: TypeConstructorDescription { + case paymentRequestedInfo(flags: Int32, name: String?, phone: String?, email: String?, shippingAddress: Api.PostAddress?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentRequestedInfo(let flags, let name, let phone, let email, let shippingAddress): + if boxed { + buffer.appendInt32(-1868808300) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(name!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(phone!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(email!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {shippingAddress!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paymentRequestedInfo(let flags, let name, let phone, let email, let shippingAddress): + return ("paymentRequestedInfo", [("flags", String(describing: flags)), ("name", String(describing: name)), ("phone", String(describing: phone)), ("email", String(describing: email)), ("shippingAddress", String(describing: shippingAddress))]) + } + } + + public static func parse_paymentRequestedInfo(_ reader: BufferReader) -> PaymentRequestedInfo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: String? + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } + var _4: String? + if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) } + var _5: Api.PostAddress? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.PostAddress + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.PaymentRequestedInfo.paymentRequestedInfo(flags: _1!, name: _2, phone: _3, email: _4, shippingAddress: _5) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PaymentSavedCredentials: TypeConstructorDescription { + case paymentSavedCredentialsCard(id: String, title: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentSavedCredentialsCard(let id, let title): + if boxed { + buffer.appendInt32(-842892769) + } + serializeString(id, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paymentSavedCredentialsCard(let id, let title): + return ("paymentSavedCredentialsCard", [("id", String(describing: id)), ("title", String(describing: title))]) + } + } + + public static func parse_paymentSavedCredentialsCard(_ reader: BufferReader) -> PaymentSavedCredentials? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PaymentSavedCredentials.paymentSavedCredentialsCard(id: _1!, title: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum Peer: TypeConstructorDescription { + case peerChannel(channelId: Int64) + case peerChat(chatId: Int64) + case peerUser(userId: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerChannel(let channelId): + if boxed { + buffer.appendInt32(-1566230754) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + break + case .peerChat(let chatId): + if boxed { + buffer.appendInt32(918946202) + } serializeInt64(chatId, buffer: buffer, boxed: false) break - case .recentMeUrlChatInvite(let url, let chatInvite): + case .peerUser(let userId): if boxed { - buffer.appendInt32(-347535331) + buffer.appendInt32(1498486562) } - serializeString(url, buffer: buffer, boxed: false) - chatInvite.serialize(buffer, true) - break - case .recentMeUrlStickerSet(let url, let set): - if boxed { - buffer.appendInt32(-1140172836) - } - serializeString(url, buffer: buffer, boxed: false) - set.serialize(buffer, true) - break - case .recentMeUrlUnknown(let url): - if boxed { - buffer.appendInt32(1189204285) - } - serializeString(url, buffer: buffer, boxed: false) - break - case .recentMeUrlUser(let url, let userId): - if boxed { - buffer.appendInt32(-1188296222) - } - serializeString(url, buffer: buffer, boxed: false) serializeInt64(userId, buffer: buffer, boxed: false) break } @@ -913,85 +491,775 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .recentMeUrlChat(let url, let chatId): - return ("recentMeUrlChat", [("url", String(describing: url)), ("chatId", String(describing: chatId))]) - case .recentMeUrlChatInvite(let url, let chatInvite): - return ("recentMeUrlChatInvite", [("url", String(describing: url)), ("chatInvite", String(describing: chatInvite))]) - case .recentMeUrlStickerSet(let url, let set): - return ("recentMeUrlStickerSet", [("url", String(describing: url)), ("set", String(describing: set))]) - case .recentMeUrlUnknown(let url): - return ("recentMeUrlUnknown", [("url", String(describing: url))]) - case .recentMeUrlUser(let url, let userId): - return ("recentMeUrlUser", [("url", String(describing: url)), ("userId", String(describing: userId))]) + case .peerChannel(let channelId): + return ("peerChannel", [("channelId", String(describing: channelId))]) + case .peerChat(let chatId): + return ("peerChat", [("chatId", String(describing: chatId))]) + case .peerUser(let userId): + return ("peerUser", [("userId", String(describing: userId))]) } } - public static func parse_recentMeUrlChat(_ reader: BufferReader) -> RecentMeUrl? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RecentMeUrl.recentMeUrlChat(url: _1!, chatId: _2!) - } - else { - return nil - } - } - public static func parse_recentMeUrlChatInvite(_ reader: BufferReader) -> RecentMeUrl? { - var _1: String? - _1 = parseString(reader) - var _2: Api.ChatInvite? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.ChatInvite - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RecentMeUrl.recentMeUrlChatInvite(url: _1!, chatInvite: _2!) - } - else { - return nil - } - } - public static func parse_recentMeUrlStickerSet(_ reader: BufferReader) -> RecentMeUrl? { - var _1: String? - _1 = parseString(reader) - var _2: Api.StickerSetCovered? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.StickerSetCovered - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RecentMeUrl.recentMeUrlStickerSet(url: _1!, set: _2!) - } - else { - return nil - } - } - public static func parse_recentMeUrlUnknown(_ reader: BufferReader) -> RecentMeUrl? { - var _1: String? - _1 = parseString(reader) + public static func parse_peerChannel(_ reader: BufferReader) -> Peer? { + var _1: Int64? + _1 = reader.readInt64() let _c1 = _1 != nil if _c1 { - return Api.RecentMeUrl.recentMeUrlUnknown(url: _1!) + return Api.Peer.peerChannel(channelId: _1!) } else { return nil } } - public static func parse_recentMeUrlUser(_ reader: BufferReader) -> RecentMeUrl? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() + public static func parse_peerChat(_ reader: BufferReader) -> Peer? { + var _1: Int64? + _1 = reader.readInt64() let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RecentMeUrl.recentMeUrlUser(url: _1!, userId: _2!) + if _c1 { + return Api.Peer.peerChat(chatId: _1!) + } + else { + return nil + } + } + public static func parse_peerUser(_ reader: BufferReader) -> Peer? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.Peer.peerUser(userId: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PeerBlocked: TypeConstructorDescription { + case peerBlocked(peerId: Api.Peer, date: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerBlocked(let peerId, let date): + if boxed { + buffer.appendInt32(-386039788) + } + peerId.serialize(buffer, true) + serializeInt32(date, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerBlocked(let peerId, let date): + return ("peerBlocked", [("peerId", String(describing: peerId)), ("date", String(describing: date))]) + } + } + + public static func parse_peerBlocked(_ reader: BufferReader) -> PeerBlocked? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PeerBlocked.peerBlocked(peerId: _1!, date: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PeerLocated: TypeConstructorDescription { + case peerLocated(peer: Api.Peer, expires: Int32, distance: Int32) + case peerSelfLocated(expires: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerLocated(let peer, let expires, let distance): + if boxed { + buffer.appendInt32(-901375139) + } + peer.serialize(buffer, true) + serializeInt32(expires, buffer: buffer, boxed: false) + serializeInt32(distance, buffer: buffer, boxed: false) + break + case .peerSelfLocated(let expires): + if boxed { + buffer.appendInt32(-118740917) + } + serializeInt32(expires, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerLocated(let peer, let expires, let distance): + return ("peerLocated", [("peer", String(describing: peer)), ("expires", String(describing: expires)), ("distance", String(describing: distance))]) + case .peerSelfLocated(let expires): + return ("peerSelfLocated", [("expires", String(describing: expires))]) + } + } + + public static func parse_peerLocated(_ reader: BufferReader) -> PeerLocated? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.PeerLocated.peerLocated(peer: _1!, expires: _2!, distance: _3!) + } + else { + return nil + } + } + public static func parse_peerSelfLocated(_ reader: BufferReader) -> PeerLocated? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.PeerLocated.peerSelfLocated(expires: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PeerNotifySettings: TypeConstructorDescription { + case peerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, iosSound: Api.NotificationSound?, androidSound: Api.NotificationSound?, otherSound: Api.NotificationSound?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound): + if boxed { + buffer.appendInt32(-1472527322) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {iosSound!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {androidSound!.serialize(buffer, true)} + if Int(flags) & Int(1 << 5) != 0 {otherSound!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let iosSound, let androidSound, let otherSound): + return ("peerNotifySettings", [("flags", String(describing: flags)), ("showPreviews", String(describing: showPreviews)), ("silent", String(describing: silent)), ("muteUntil", String(describing: muteUntil)), ("iosSound", String(describing: iosSound)), ("androidSound", String(describing: androidSound)), ("otherSound", String(describing: otherSound))]) + } + } + + public static func parse_peerNotifySettings(_ reader: BufferReader) -> PeerNotifySettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Bool? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Bool + } } + var _3: Api.Bool? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Bool + } } + var _4: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } + var _5: Api.NotificationSound? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.NotificationSound + } } + var _6: Api.NotificationSound? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.NotificationSound + } } + var _7: Api.NotificationSound? + if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.NotificationSound + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 5) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.PeerNotifySettings.peerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, iosSound: _5, androidSound: _6, otherSound: _7) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PeerSettings: TypeConstructorDescription { + case peerSettings(flags: Int32, geoDistance: Int32?, requestChatTitle: String?, requestChatDate: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerSettings(let flags, let geoDistance, let requestChatTitle, let requestChatDate): + if boxed { + buffer.appendInt32(-1525149427) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(geoDistance!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 9) != 0 {serializeString(requestChatTitle!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 9) != 0 {serializeInt32(requestChatDate!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerSettings(let flags, let geoDistance, let requestChatTitle, let requestChatDate): + return ("peerSettings", [("flags", String(describing: flags)), ("geoDistance", String(describing: geoDistance)), ("requestChatTitle", String(describing: requestChatTitle)), ("requestChatDate", String(describing: requestChatDate))]) + } + } + + public static func parse_peerSettings(_ reader: BufferReader) -> PeerSettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_2 = reader.readInt32() } + var _3: String? + if Int(_1!) & Int(1 << 9) != 0 {_3 = parseString(reader) } + var _4: Int32? + if Int(_1!) & Int(1 << 9) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 6) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 9) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 9) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PeerSettings.peerSettings(flags: _1!, geoDistance: _2, requestChatTitle: _3, requestChatDate: _4) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PhoneCall: TypeConstructorDescription { + case phoneCall(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAOrB: Buffer, keyFingerprint: Int64, protocol: Api.PhoneCallProtocol, connections: [Api.PhoneConnection], startDate: Int32) + case phoneCallAccepted(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gB: Buffer, protocol: Api.PhoneCallProtocol) + case phoneCallDiscarded(flags: Int32, id: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) + case phoneCallEmpty(id: Int64) + case phoneCallRequested(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, gAHash: Buffer, protocol: Api.PhoneCallProtocol) + case phoneCallWaiting(flags: Int32, id: Int64, accessHash: Int64, date: Int32, adminId: Int64, participantId: Int64, protocol: Api.PhoneCallProtocol, receiveDate: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCall(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAOrB, let keyFingerprint, let `protocol`, let connections, let startDate): + if boxed { + buffer.appendInt32(-1770029977) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(adminId, buffer: buffer, boxed: false) + serializeInt64(participantId, buffer: buffer, boxed: false) + serializeBytes(gAOrB, buffer: buffer, boxed: false) + serializeInt64(keyFingerprint, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(connections.count)) + for item in connections { + item.serialize(buffer, true) + } + serializeInt32(startDate, buffer: buffer, boxed: false) + break + case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`): + if boxed { + buffer.appendInt32(912311057) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(adminId, buffer: buffer, boxed: false) + serializeInt64(participantId, buffer: buffer, boxed: false) + serializeBytes(gB, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + break + case .phoneCallDiscarded(let flags, let id, let reason, let duration): + if boxed { + buffer.appendInt32(1355435489) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} + break + case .phoneCallEmpty(let id): + if boxed { + buffer.appendInt32(1399245077) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`): + if boxed { + buffer.appendInt32(347139340) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(adminId, buffer: buffer, boxed: false) + serializeInt64(participantId, buffer: buffer, boxed: false) + serializeBytes(gAHash, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + break + case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate): + if boxed { + buffer.appendInt32(-987599081) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(adminId, buffer: buffer, boxed: false) + serializeInt64(participantId, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(receiveDate!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneCall(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAOrB, let keyFingerprint, let `protocol`, let connections, let startDate): + return ("phoneCall", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gAOrB", String(describing: gAOrB)), ("keyFingerprint", String(describing: keyFingerprint)), ("`protocol`", String(describing: `protocol`)), ("connections", String(describing: connections)), ("startDate", String(describing: startDate))]) + case .phoneCallAccepted(let flags, let id, let accessHash, let date, let adminId, let participantId, let gB, let `protocol`): + return ("phoneCallAccepted", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gB", String(describing: gB)), ("`protocol`", String(describing: `protocol`))]) + case .phoneCallDiscarded(let flags, let id, let reason, let duration): + return ("phoneCallDiscarded", [("flags", String(describing: flags)), ("id", String(describing: id)), ("reason", String(describing: reason)), ("duration", String(describing: duration))]) + case .phoneCallEmpty(let id): + return ("phoneCallEmpty", [("id", String(describing: id))]) + case .phoneCallRequested(let flags, let id, let accessHash, let date, let adminId, let participantId, let gAHash, let `protocol`): + return ("phoneCallRequested", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]) + case .phoneCallWaiting(let flags, let id, let accessHash, let date, let adminId, let participantId, let `protocol`, let receiveDate): + return ("phoneCallWaiting", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("date", String(describing: date)), ("adminId", String(describing: adminId)), ("participantId", String(describing: participantId)), ("`protocol`", String(describing: `protocol`)), ("receiveDate", String(describing: receiveDate))]) + } + } + + public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int64? + _5 = reader.readInt64() + var _6: Int64? + _6 = reader.readInt64() + var _7: Buffer? + _7 = parseBytes(reader) + var _8: Int64? + _8 = reader.readInt64() + var _9: Api.PhoneCallProtocol? + if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol + } + var _10: [Api.PhoneConnection]? + if let _ = reader.readInt32() { + _10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhoneConnection.self) + } + var _11: Int32? + _11 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = _10 != nil + let _c11 = _11 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 { + return Api.PhoneCall.phoneCall(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAOrB: _7!, keyFingerprint: _8!, protocol: _9!, connections: _10!, startDate: _11!) + } + else { + return nil + } + } + public static func parse_phoneCallAccepted(_ reader: BufferReader) -> PhoneCall? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int64? + _5 = reader.readInt64() + var _6: Int64? + _6 = reader.readInt64() + var _7: Buffer? + _7 = parseBytes(reader) + var _8: Api.PhoneCallProtocol? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.PhoneCall.phoneCallAccepted(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gB: _7!, protocol: _8!) + } + else { + return nil + } + } + public static func parse_phoneCallDiscarded(_ reader: BufferReader) -> PhoneCall? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.PhoneCallDiscardReason? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.PhoneCallDiscardReason + } } + var _4: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PhoneCall.phoneCallDiscarded(flags: _1!, id: _2!, reason: _3, duration: _4) + } + else { + return nil + } + } + public static func parse_phoneCallEmpty(_ reader: BufferReader) -> PhoneCall? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.PhoneCall.phoneCallEmpty(id: _1!) + } + else { + return nil + } + } + public static func parse_phoneCallRequested(_ reader: BufferReader) -> PhoneCall? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int64? + _5 = reader.readInt64() + var _6: Int64? + _6 = reader.readInt64() + var _7: Buffer? + _7 = parseBytes(reader) + var _8: Api.PhoneCallProtocol? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.PhoneCall.phoneCallRequested(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, gAHash: _7!, protocol: _8!) + } + else { + return nil + } + } + public static func parse_phoneCallWaiting(_ reader: BufferReader) -> PhoneCall? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int64? + _5 = reader.readInt64() + var _6: Int64? + _6 = reader.readInt64() + var _7: Api.PhoneCallProtocol? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.PhoneCallProtocol + } + var _8: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_8 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = (Int(_1!) & Int(1 << 0) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.PhoneCall.phoneCallWaiting(flags: _1!, id: _2!, accessHash: _3!, date: _4!, adminId: _5!, participantId: _6!, protocol: _7!, receiveDate: _8) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PhoneCallDiscardReason: TypeConstructorDescription { + case phoneCallDiscardReasonBusy + case phoneCallDiscardReasonDisconnect + case phoneCallDiscardReasonHangup + case phoneCallDiscardReasonMissed + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCallDiscardReasonBusy: + if boxed { + buffer.appendInt32(-84416311) + } + + break + case .phoneCallDiscardReasonDisconnect: + if boxed { + buffer.appendInt32(-527056480) + } + + break + case .phoneCallDiscardReasonHangup: + if boxed { + buffer.appendInt32(1471006352) + } + + break + case .phoneCallDiscardReasonMissed: + if boxed { + buffer.appendInt32(-2048646399) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneCallDiscardReasonBusy: + return ("phoneCallDiscardReasonBusy", []) + case .phoneCallDiscardReasonDisconnect: + return ("phoneCallDiscardReasonDisconnect", []) + case .phoneCallDiscardReasonHangup: + return ("phoneCallDiscardReasonHangup", []) + case .phoneCallDiscardReasonMissed: + return ("phoneCallDiscardReasonMissed", []) + } + } + + public static func parse_phoneCallDiscardReasonBusy(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonBusy + } + public static func parse_phoneCallDiscardReasonDisconnect(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonDisconnect + } + public static func parse_phoneCallDiscardReasonHangup(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonHangup + } + public static func parse_phoneCallDiscardReasonMissed(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonMissed + } + + } +} +public extension Api { + enum PhoneCallProtocol: TypeConstructorDescription { + case phoneCallProtocol(flags: Int32, minLayer: Int32, maxLayer: Int32, libraryVersions: [String]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCallProtocol(let flags, let minLayer, let maxLayer, let libraryVersions): + if boxed { + buffer.appendInt32(-58224696) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(minLayer, buffer: buffer, boxed: false) + serializeInt32(maxLayer, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(libraryVersions.count)) + for item in libraryVersions { + serializeString(item, buffer: buffer, boxed: false) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneCallProtocol(let flags, let minLayer, let maxLayer, let libraryVersions): + return ("phoneCallProtocol", [("flags", String(describing: flags)), ("minLayer", String(describing: minLayer)), ("maxLayer", String(describing: maxLayer)), ("libraryVersions", String(describing: libraryVersions))]) + } + } + + public static func parse_phoneCallProtocol(_ reader: BufferReader) -> PhoneCallProtocol? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: [String]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PhoneCallProtocol.phoneCallProtocol(flags: _1!, minLayer: _2!, maxLayer: _3!, libraryVersions: _4!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PhoneConnection: TypeConstructorDescription { + case phoneConnection(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, peerTag: Buffer) + case phoneConnectionWebrtc(flags: Int32, id: Int64, ip: String, ipv6: String, port: Int32, username: String, password: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag): + if boxed { + buffer.appendInt32(-1665063993) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeString(ip, buffer: buffer, boxed: false) + serializeString(ipv6, buffer: buffer, boxed: false) + serializeInt32(port, buffer: buffer, boxed: false) + serializeBytes(peerTag, buffer: buffer, boxed: false) + break + case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password): + if boxed { + buffer.appendInt32(1667228533) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeString(ip, buffer: buffer, boxed: false) + serializeString(ipv6, buffer: buffer, boxed: false) + serializeInt32(port, buffer: buffer, boxed: false) + serializeString(username, buffer: buffer, boxed: false) + serializeString(password, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneConnection(let flags, let id, let ip, let ipv6, let port, let peerTag): + return ("phoneConnection", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("peerTag", String(describing: peerTag))]) + case .phoneConnectionWebrtc(let flags, let id, let ip, let ipv6, let port, let username, let password): + return ("phoneConnectionWebrtc", [("flags", String(describing: flags)), ("id", String(describing: id)), ("ip", String(describing: ip)), ("ipv6", String(describing: ipv6)), ("port", String(describing: port)), ("username", String(describing: username)), ("password", String(describing: password))]) + } + } + + public static func parse_phoneConnection(_ reader: BufferReader) -> PhoneConnection? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: Buffer? + _6 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.PhoneConnection.phoneConnection(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, peerTag: _6!) + } + else { + return nil + } + } + public static func parse_phoneConnectionWebrtc(_ reader: BufferReader) -> PhoneConnection? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: String? + _6 = parseString(reader) + var _7: String? + _7 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.PhoneConnection.phoneConnectionWebrtc(flags: _1!, id: _2!, ip: _3!, ipv6: _4!, port: _5!, username: _6!, password: _7!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 916951a39e..2c3236c9e6 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -1,295 +1,91 @@ public extension Api { - enum ReplyMarkup: TypeConstructorDescription { - case replyInlineMarkup(rows: [Api.KeyboardButtonRow]) - case replyKeyboardForceReply(flags: Int32, placeholder: String?) - case replyKeyboardHide(flags: Int32) - case replyKeyboardMarkup(flags: Int32, rows: [Api.KeyboardButtonRow], placeholder: String?) + enum Photo: TypeConstructorDescription { + case photo(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, sizes: [Api.PhotoSize], videoSizes: [Api.VideoSize]?, dcId: Int32) + case photoEmpty(id: Int64) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .replyInlineMarkup(let rows): + case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let videoSizes, let dcId): if boxed { - buffer.appendInt32(1218642516) + buffer.appendInt32(-82216347) } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeBytes(fileReference, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rows.count)) - for item in rows { + buffer.appendInt32(Int32(sizes.count)) + for item in sizes { item.serialize(buffer, true) } - break - case .replyKeyboardForceReply(let flags, let placeholder): - if boxed { - buffer.appendInt32(-2035021048) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {serializeString(placeholder!, buffer: buffer, boxed: false)} - break - case .replyKeyboardHide(let flags): - if boxed { - buffer.appendInt32(-1606526075) - } - serializeInt32(flags, buffer: buffer, boxed: false) - break - case .replyKeyboardMarkup(let flags, let rows, let placeholder): - if boxed { - buffer.appendInt32(-2049074735) - } - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rows.count)) - for item in rows { + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(videoSizes!.count)) + for item in videoSizes! { item.serialize(buffer, true) + }} + serializeInt32(dcId, buffer: buffer, boxed: false) + break + case .photoEmpty(let id): + if boxed { + buffer.appendInt32(590459437) } - if Int(flags) & Int(1 << 3) != 0 {serializeString(placeholder!, buffer: buffer, boxed: false)} + serializeInt64(id, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .replyInlineMarkup(let rows): - return ("replyInlineMarkup", [("rows", String(describing: rows))]) - case .replyKeyboardForceReply(let flags, let placeholder): - return ("replyKeyboardForceReply", [("flags", String(describing: flags)), ("placeholder", String(describing: placeholder))]) - case .replyKeyboardHide(let flags): - return ("replyKeyboardHide", [("flags", String(describing: flags))]) - case .replyKeyboardMarkup(let flags, let rows, let placeholder): - return ("replyKeyboardMarkup", [("flags", String(describing: flags)), ("rows", String(describing: rows)), ("placeholder", String(describing: placeholder))]) + case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let videoSizes, let dcId): + return ("photo", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("fileReference", String(describing: fileReference)), ("date", String(describing: date)), ("sizes", String(describing: sizes)), ("videoSizes", String(describing: videoSizes)), ("dcId", String(describing: dcId))]) + case .photoEmpty(let id): + return ("photoEmpty", [("id", String(describing: id))]) } } - public static func parse_replyInlineMarkup(_ reader: BufferReader) -> ReplyMarkup? { - var _1: [Api.KeyboardButtonRow]? + public static func parse_photo(_ reader: BufferReader) -> Photo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Buffer? + _4 = parseBytes(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: [Api.PhotoSize]? if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButtonRow.self) + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self) } - let _c1 = _1 != nil - if _c1 { - return Api.ReplyMarkup.replyInlineMarkup(rows: _1!) - } - else { - return nil - } - } - public static func parse_replyKeyboardForceReply(_ reader: BufferReader) -> ReplyMarkup? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 3) != 0 {_2 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil - if _c1 && _c2 { - return Api.ReplyMarkup.replyKeyboardForceReply(flags: _1!, placeholder: _2) - } - else { - return nil - } - } - public static func parse_replyKeyboardHide(_ reader: BufferReader) -> ReplyMarkup? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.ReplyMarkup.replyKeyboardHide(flags: _1!) - } - else { - return nil - } - } - public static func parse_replyKeyboardMarkup(_ reader: BufferReader) -> ReplyMarkup? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.KeyboardButtonRow]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButtonRow.self) - } - var _3: String? - if Int(_1!) & Int(1 << 3) != 0 {_3 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.ReplyMarkup.replyKeyboardMarkup(flags: _1!, rows: _2!, placeholder: _3) - } - else { - return nil - } - } - - } -} -public extension Api { - enum ReportReason: TypeConstructorDescription { - case inputReportReasonChildAbuse - case inputReportReasonCopyright - case inputReportReasonFake - case inputReportReasonGeoIrrelevant - case inputReportReasonIllegalDrugs - case inputReportReasonOther - case inputReportReasonPersonalDetails - case inputReportReasonPornography - case inputReportReasonSpam - case inputReportReasonViolence - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputReportReasonChildAbuse: - if boxed { - buffer.appendInt32(-1376497949) - } - - break - case .inputReportReasonCopyright: - if boxed { - buffer.appendInt32(-1685456582) - } - - break - case .inputReportReasonFake: - if boxed { - buffer.appendInt32(-170010905) - } - - break - case .inputReportReasonGeoIrrelevant: - if boxed { - buffer.appendInt32(-606798099) - } - - break - case .inputReportReasonIllegalDrugs: - if boxed { - buffer.appendInt32(177124030) - } - - break - case .inputReportReasonOther: - if boxed { - buffer.appendInt32(-1041980751) - } - - break - case .inputReportReasonPersonalDetails: - if boxed { - buffer.appendInt32(-1631091139) - } - - break - case .inputReportReasonPornography: - if boxed { - buffer.appendInt32(777640226) - } - - break - case .inputReportReasonSpam: - if boxed { - buffer.appendInt32(1490799288) - } - - break - case .inputReportReasonViolence: - if boxed { - buffer.appendInt32(505595789) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputReportReasonChildAbuse: - return ("inputReportReasonChildAbuse", []) - case .inputReportReasonCopyright: - return ("inputReportReasonCopyright", []) - case .inputReportReasonFake: - return ("inputReportReasonFake", []) - case .inputReportReasonGeoIrrelevant: - return ("inputReportReasonGeoIrrelevant", []) - case .inputReportReasonIllegalDrugs: - return ("inputReportReasonIllegalDrugs", []) - case .inputReportReasonOther: - return ("inputReportReasonOther", []) - case .inputReportReasonPersonalDetails: - return ("inputReportReasonPersonalDetails", []) - case .inputReportReasonPornography: - return ("inputReportReasonPornography", []) - case .inputReportReasonSpam: - return ("inputReportReasonSpam", []) - case .inputReportReasonViolence: - return ("inputReportReasonViolence", []) - } - } - - public static func parse_inputReportReasonChildAbuse(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonChildAbuse - } - public static func parse_inputReportReasonCopyright(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonCopyright - } - public static func parse_inputReportReasonFake(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonFake - } - public static func parse_inputReportReasonGeoIrrelevant(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonGeoIrrelevant - } - public static func parse_inputReportReasonIllegalDrugs(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonIllegalDrugs - } - public static func parse_inputReportReasonOther(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonOther - } - public static func parse_inputReportReasonPersonalDetails(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonPersonalDetails - } - public static func parse_inputReportReasonPornography(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonPornography - } - public static func parse_inputReportReasonSpam(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonSpam - } - public static func parse_inputReportReasonViolence(_ reader: BufferReader) -> ReportReason? { - return Api.ReportReason.inputReportReasonViolence - } - - } -} -public extension Api { - enum RestrictionReason: TypeConstructorDescription { - case restrictionReason(platform: String, reason: String, text: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .restrictionReason(let platform, let reason, let text): - if boxed { - buffer.appendInt32(-797791052) - } - serializeString(platform, buffer: buffer, boxed: false) - serializeString(reason, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .restrictionReason(let platform, let reason, let text): - return ("restrictionReason", [("platform", String(describing: platform)), ("reason", String(describing: reason)), ("text", String(describing: text))]) - } - } - - public static func parse_restrictionReason(_ reader: BufferReader) -> RestrictionReason? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) + var _7: [Api.VideoSize]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.VideoSize.self) + } } + var _8: Int32? + _8 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.RestrictionReason.restrictionReason(platform: _1!, reason: _2!, text: _3!) + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.Photo.photo(flags: _1!, id: _2!, accessHash: _3!, fileReference: _4!, date: _5!, sizes: _6!, videoSizes: _7, dcId: _8!) + } + else { + return nil + } + } + public static func parse_photoEmpty(_ reader: BufferReader) -> Photo? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.Photo.photoEmpty(id: _1!) } else { return nil @@ -299,423 +95,128 @@ public extension Api { } } public extension Api { - indirect enum RichText: TypeConstructorDescription { - case textAnchor(text: Api.RichText, name: String) - case textBold(text: Api.RichText) - case textConcat(texts: [Api.RichText]) - case textEmail(text: Api.RichText, email: String) - case textEmpty - case textFixed(text: Api.RichText) - case textImage(documentId: Int64, w: Int32, h: Int32) - case textItalic(text: Api.RichText) - case textMarked(text: Api.RichText) - case textPhone(text: Api.RichText, phone: String) - case textPlain(text: String) - case textStrike(text: Api.RichText) - case textSubscript(text: Api.RichText) - case textSuperscript(text: Api.RichText) - case textUnderline(text: Api.RichText) - case textUrl(text: Api.RichText, url: String, webpageId: Int64) + enum PhotoSize: TypeConstructorDescription { + case photoCachedSize(type: String, w: Int32, h: Int32, bytes: Buffer) + case photoPathSize(type: String, bytes: Buffer) + case photoSize(type: String, w: Int32, h: Int32, size: Int32) + case photoSizeEmpty(type: String) + case photoSizeProgressive(type: String, w: Int32, h: Int32, sizes: [Int32]) + case photoStrippedSize(type: String, bytes: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .textAnchor(let text, let name): + case .photoCachedSize(let type, let w, let h, let bytes): if boxed { - buffer.appendInt32(894777186) + buffer.appendInt32(35527382) } - text.serialize(buffer, true) - serializeString(name, buffer: buffer, boxed: false) - break - case .textBold(let text): - if boxed { - buffer.appendInt32(1730456516) - } - text.serialize(buffer, true) - break - case .textConcat(let texts): - if boxed { - buffer.appendInt32(2120376535) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(texts.count)) - for item in texts { - item.serialize(buffer, true) - } - break - case .textEmail(let text, let email): - if boxed { - buffer.appendInt32(-564523562) - } - text.serialize(buffer, true) - serializeString(email, buffer: buffer, boxed: false) - break - case .textEmpty: - if boxed { - buffer.appendInt32(-599948721) - } - - break - case .textFixed(let text): - if boxed { - buffer.appendInt32(1816074681) - } - text.serialize(buffer, true) - break - case .textImage(let documentId, let w, let h): - if boxed { - buffer.appendInt32(136105807) - } - serializeInt64(documentId, buffer: buffer, boxed: false) + serializeString(type, buffer: buffer, boxed: false) serializeInt32(w, buffer: buffer, boxed: false) serializeInt32(h, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) break - case .textItalic(let text): + case .photoPathSize(let type, let bytes): if boxed { - buffer.appendInt32(-653089380) + buffer.appendInt32(-668906175) } - text.serialize(buffer, true) + serializeString(type, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) break - case .textMarked(let text): + case .photoSize(let type, let w, let h, let size): if boxed { - buffer.appendInt32(55281185) + buffer.appendInt32(1976012384) } - text.serialize(buffer, true) + serializeString(type, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + serializeInt32(size, buffer: buffer, boxed: false) break - case .textPhone(let text, let phone): + case .photoSizeEmpty(let type): if boxed { - buffer.appendInt32(483104362) + buffer.appendInt32(236446268) } - text.serialize(buffer, true) - serializeString(phone, buffer: buffer, boxed: false) + serializeString(type, buffer: buffer, boxed: false) break - case .textPlain(let text): + case .photoSizeProgressive(let type, let w, let h, let sizes): if boxed { - buffer.appendInt32(1950782688) + buffer.appendInt32(-96535659) + } + serializeString(type, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sizes.count)) + for item in sizes { + serializeInt32(item, buffer: buffer, boxed: false) } - serializeString(text, buffer: buffer, boxed: false) break - case .textStrike(let text): + case .photoStrippedSize(let type, let bytes): if boxed { - buffer.appendInt32(-1678197867) + buffer.appendInt32(-525288402) } - text.serialize(buffer, true) - break - case .textSubscript(let text): - if boxed { - buffer.appendInt32(-311786236) - } - text.serialize(buffer, true) - break - case .textSuperscript(let text): - if boxed { - buffer.appendInt32(-939827711) - } - text.serialize(buffer, true) - break - case .textUnderline(let text): - if boxed { - buffer.appendInt32(-1054465340) - } - text.serialize(buffer, true) - break - case .textUrl(let text, let url, let webpageId): - if boxed { - buffer.appendInt32(1009288385) - } - text.serialize(buffer, true) - serializeString(url, buffer: buffer, boxed: false) - serializeInt64(webpageId, buffer: buffer, boxed: false) + serializeString(type, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .textAnchor(let text, let name): - return ("textAnchor", [("text", String(describing: text)), ("name", String(describing: name))]) - case .textBold(let text): - return ("textBold", [("text", String(describing: text))]) - case .textConcat(let texts): - return ("textConcat", [("texts", String(describing: texts))]) - case .textEmail(let text, let email): - return ("textEmail", [("text", String(describing: text)), ("email", String(describing: email))]) - case .textEmpty: - return ("textEmpty", []) - case .textFixed(let text): - return ("textFixed", [("text", String(describing: text))]) - case .textImage(let documentId, let w, let h): - return ("textImage", [("documentId", String(describing: documentId)), ("w", String(describing: w)), ("h", String(describing: h))]) - case .textItalic(let text): - return ("textItalic", [("text", String(describing: text))]) - case .textMarked(let text): - return ("textMarked", [("text", String(describing: text))]) - case .textPhone(let text, let phone): - return ("textPhone", [("text", String(describing: text)), ("phone", String(describing: phone))]) - case .textPlain(let text): - return ("textPlain", [("text", String(describing: text))]) - case .textStrike(let text): - return ("textStrike", [("text", String(describing: text))]) - case .textSubscript(let text): - return ("textSubscript", [("text", String(describing: text))]) - case .textSuperscript(let text): - return ("textSuperscript", [("text", String(describing: text))]) - case .textUnderline(let text): - return ("textUnderline", [("text", String(describing: text))]) - case .textUrl(let text, let url, let webpageId): - return ("textUrl", [("text", String(describing: text)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId))]) + case .photoCachedSize(let type, let w, let h, let bytes): + return ("photoCachedSize", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("bytes", String(describing: bytes))]) + case .photoPathSize(let type, let bytes): + return ("photoPathSize", [("type", String(describing: type)), ("bytes", String(describing: bytes))]) + case .photoSize(let type, let w, let h, let size): + return ("photoSize", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("size", String(describing: size))]) + case .photoSizeEmpty(let type): + return ("photoSizeEmpty", [("type", String(describing: type))]) + case .photoSizeProgressive(let type, let w, let h, let sizes): + return ("photoSizeProgressive", [("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("sizes", String(describing: sizes))]) + case .photoStrippedSize(let type, let bytes): + return ("photoStrippedSize", [("type", String(describing: type)), ("bytes", String(describing: bytes))]) } } - public static func parse_textAnchor(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RichText.textAnchor(text: _1!, name: _2!) - } - else { - return nil - } - } - public static func parse_textBold(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textBold(text: _1!) - } - else { - return nil - } - } - public static func parse_textConcat(_ reader: BufferReader) -> RichText? { - var _1: [Api.RichText]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RichText.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textConcat(texts: _1!) - } - else { - return nil - } - } - public static func parse_textEmail(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.RichText.textEmail(text: _1!, email: _2!) - } - else { - return nil - } - } - public static func parse_textEmpty(_ reader: BufferReader) -> RichText? { - return Api.RichText.textEmpty - } - public static func parse_textFixed(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textFixed(text: _1!) - } - else { - return nil - } - } - public static func parse_textImage(_ reader: BufferReader) -> RichText? { - var _1: Int64? - _1 = reader.readInt64() + public static func parse_photoCachedSize(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) var _2: Int32? _2 = reader.readInt32() var _3: Int32? _3 = reader.readInt32() + var _4: Buffer? + _4 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.RichText.textImage(documentId: _1!, w: _2!, h: _3!) + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PhotoSize.photoCachedSize(type: _1!, w: _2!, h: _3!, bytes: _4!) } else { return nil } } - public static func parse_textItalic(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textItalic(text: _1!) - } - else { - return nil - } - } - public static func parse_textMarked(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textMarked(text: _1!) - } - else { - return nil - } - } - public static func parse_textPhone(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: String? - _2 = parseString(reader) + public static func parse_photoPathSize(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) + var _2: Buffer? + _2 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.RichText.textPhone(text: _1!, phone: _2!) + return Api.PhotoSize.photoPathSize(type: _1!, bytes: _2!) } else { return nil } } - public static func parse_textPlain(_ reader: BufferReader) -> RichText? { + public static func parse_photoSize(_ reader: BufferReader) -> PhotoSize? { var _1: String? _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textPlain(text: _1!) - } - else { - return nil - } - } - public static func parse_textStrike(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textStrike(text: _1!) - } - else { - return nil - } - } - public static func parse_textSubscript(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textSubscript(text: _1!) - } - else { - return nil - } - } - public static func parse_textSuperscript(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textSuperscript(text: _1!) - } - else { - return nil - } - } - public static func parse_textUnderline(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - let _c1 = _1 != nil - if _c1 { - return Api.RichText.textUnderline(text: _1!) - } - else { - return nil - } - } - public static func parse_textUrl(_ reader: BufferReader) -> RichText? { - var _1: Api.RichText? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.RichText - } - var _2: String? - _2 = parseString(reader) - var _3: Int64? - _3 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.RichText.textUrl(text: _1!, url: _2!, webpageId: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SavedContact: TypeConstructorDescription { - case savedPhoneContact(phone: String, firstName: String, lastName: String, date: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .savedPhoneContact(let phone, let firstName, let lastName, let date): - if boxed { - buffer.appendInt32(289586518) - } - serializeString(phone, buffer: buffer, boxed: false) - serializeString(firstName, buffer: buffer, boxed: false) - serializeString(lastName, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .savedPhoneContact(let phone, let firstName, let lastName, let date): - return ("savedPhoneContact", [("phone", String(describing: phone)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("date", String(describing: date))]) - } - } - - public static func parse_savedPhoneContact(_ reader: BufferReader) -> SavedContact? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() var _4: Int32? _4 = reader.readInt32() let _c1 = _1 != nil @@ -723,7 +224,718 @@ public extension Api { let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.SavedContact.savedPhoneContact(phone: _1!, firstName: _2!, lastName: _3!, date: _4!) + return Api.PhotoSize.photoSize(type: _1!, w: _2!, h: _3!, size: _4!) + } + else { + return nil + } + } + public static func parse_photoSizeEmpty(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.PhotoSize.photoSizeEmpty(type: _1!) + } + else { + return nil + } + } + public static func parse_photoSizeProgressive(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: [Int32]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.PhotoSize.photoSizeProgressive(type: _1!, w: _2!, h: _3!, sizes: _4!) + } + else { + return nil + } + } + public static func parse_photoStrippedSize(_ reader: BufferReader) -> PhotoSize? { + var _1: String? + _1 = parseString(reader) + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PhotoSize.photoStrippedSize(type: _1!, bytes: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum Poll: TypeConstructorDescription { + case poll(id: Int64, flags: Int32, question: String, answers: [Api.PollAnswer], closePeriod: Int32?, closeDate: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .poll(let id, let flags, let question, let answers, let closePeriod, let closeDate): + if boxed { + buffer.appendInt32(-2032041631) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(question, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(answers.count)) + for item in answers { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(closePeriod!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {serializeInt32(closeDate!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .poll(let id, let flags, let question, let answers, let closePeriod, let closeDate): + return ("poll", [("id", String(describing: id)), ("flags", String(describing: flags)), ("question", String(describing: question)), ("answers", String(describing: answers)), ("closePeriod", String(describing: closePeriod)), ("closeDate", String(describing: closeDate))]) + } + } + + public static func parse_poll(_ reader: BufferReader) -> Poll? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: [Api.PollAnswer]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PollAnswer.self) + } + var _5: Int32? + if Int(_2!) & Int(1 << 4) != 0 {_5 = reader.readInt32() } + var _6: Int32? + if Int(_2!) & Int(1 << 5) != 0 {_6 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_2!) & Int(1 << 4) == 0) || _5 != nil + let _c6 = (Int(_2!) & Int(1 << 5) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Poll.poll(id: _1!, flags: _2!, question: _3!, answers: _4!, closePeriod: _5, closeDate: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PollAnswer: TypeConstructorDescription { + case pollAnswer(text: String, option: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pollAnswer(let text, let option): + if boxed { + buffer.appendInt32(1823064809) + } + serializeString(text, buffer: buffer, boxed: false) + serializeBytes(option, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pollAnswer(let text, let option): + return ("pollAnswer", [("text", String(describing: text)), ("option", String(describing: option))]) + } + } + + public static func parse_pollAnswer(_ reader: BufferReader) -> PollAnswer? { + var _1: String? + _1 = parseString(reader) + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PollAnswer.pollAnswer(text: _1!, option: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PollAnswerVoters: TypeConstructorDescription { + case pollAnswerVoters(flags: Int32, option: Buffer, voters: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pollAnswerVoters(let flags, let option, let voters): + if boxed { + buffer.appendInt32(997055186) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeBytes(option, buffer: buffer, boxed: false) + serializeInt32(voters, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pollAnswerVoters(let flags, let option, let voters): + return ("pollAnswerVoters", [("flags", String(describing: flags)), ("option", String(describing: option)), ("voters", String(describing: voters))]) + } + } + + public static func parse_pollAnswerVoters(_ reader: BufferReader) -> PollAnswerVoters? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.PollAnswerVoters.pollAnswerVoters(flags: _1!, option: _2!, voters: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PollResults: TypeConstructorDescription { + case pollResults(flags: Int32, results: [Api.PollAnswerVoters]?, totalVoters: Int32?, recentVoters: [Int64]?, solution: String?, solutionEntities: [Api.MessageEntity]?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .pollResults(let flags, let results, let totalVoters, let recentVoters, let solution, let solutionEntities): + if boxed { + buffer.appendInt32(-591909213) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(results!.count)) + for item in results! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(totalVoters!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(recentVoters!.count)) + for item in recentVoters! { + serializeInt64(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 4) != 0 {serializeString(solution!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(solutionEntities!.count)) + for item in solutionEntities! { + item.serialize(buffer, true) + }} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .pollResults(let flags, let results, let totalVoters, let recentVoters, let solution, let solutionEntities): + return ("pollResults", [("flags", String(describing: flags)), ("results", String(describing: results)), ("totalVoters", String(describing: totalVoters)), ("recentVoters", String(describing: recentVoters)), ("solution", String(describing: solution)), ("solutionEntities", String(describing: solutionEntities))]) + } + } + + public static func parse_pollResults(_ reader: BufferReader) -> PollResults? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.PollAnswerVoters]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PollAnswerVoters.self) + } } + var _3: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() } + var _4: [Int64]? + if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } } + var _5: String? + if Int(_1!) & Int(1 << 4) != 0 {_5 = parseString(reader) } + var _6: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.PollResults.pollResults(flags: _1!, results: _2, totalVoters: _3, recentVoters: _4, solution: _5, solutionEntities: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PopularContact: TypeConstructorDescription { + case popularContact(clientId: Int64, importers: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .popularContact(let clientId, let importers): + if boxed { + buffer.appendInt32(1558266229) + } + serializeInt64(clientId, buffer: buffer, boxed: false) + serializeInt32(importers, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .popularContact(let clientId, let importers): + return ("popularContact", [("clientId", String(describing: clientId)), ("importers", String(describing: importers))]) + } + } + + public static func parse_popularContact(_ reader: BufferReader) -> PopularContact? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.PopularContact.popularContact(clientId: _1!, importers: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PostAddress: TypeConstructorDescription { + case postAddress(streetLine1: String, streetLine2: String, city: String, state: String, countryIso2: String, postCode: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .postAddress(let streetLine1, let streetLine2, let city, let state, let countryIso2, let postCode): + if boxed { + buffer.appendInt32(512535275) + } + serializeString(streetLine1, buffer: buffer, boxed: false) + serializeString(streetLine2, buffer: buffer, boxed: false) + serializeString(city, buffer: buffer, boxed: false) + serializeString(state, buffer: buffer, boxed: false) + serializeString(countryIso2, buffer: buffer, boxed: false) + serializeString(postCode, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .postAddress(let streetLine1, let streetLine2, let city, let state, let countryIso2, let postCode): + return ("postAddress", [("streetLine1", String(describing: streetLine1)), ("streetLine2", String(describing: streetLine2)), ("city", String(describing: city)), ("state", String(describing: state)), ("countryIso2", String(describing: countryIso2)), ("postCode", String(describing: postCode))]) + } + } + + public static func parse_postAddress(_ reader: BufferReader) -> PostAddress? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: String? + _6 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.PostAddress.postAddress(streetLine1: _1!, streetLine2: _2!, city: _3!, state: _4!, countryIso2: _5!, postCode: _6!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PremiumGiftOption: TypeConstructorDescription { + case premiumGiftOption(flags: Int32, months: Int32, currency: String, amount: Int64, botUrl: String, storeProduct: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .premiumGiftOption(let flags, let months, let currency, let amount, let botUrl, let storeProduct): + if boxed { + buffer.appendInt32(1958953753) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(months, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) + serializeString(botUrl, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(storeProduct!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .premiumGiftOption(let flags, let months, let currency, let amount, let botUrl, let storeProduct): + return ("premiumGiftOption", [("flags", String(describing: flags)), ("months", String(describing: months)), ("currency", String(describing: currency)), ("amount", String(describing: amount)), ("botUrl", String(describing: botUrl)), ("storeProduct", String(describing: storeProduct))]) + } + } + + public static func parse_premiumGiftOption(_ reader: BufferReader) -> PremiumGiftOption? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: Int64? + _4 = reader.readInt64() + var _5: String? + _5 = parseString(reader) + var _6: String? + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.PremiumGiftOption.premiumGiftOption(flags: _1!, months: _2!, currency: _3!, amount: _4!, botUrl: _5!, storeProduct: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum PrivacyKey: TypeConstructorDescription { + case privacyKeyAddedByPhone + case privacyKeyChatInvite + case privacyKeyForwards + case privacyKeyPhoneCall + case privacyKeyPhoneNumber + case privacyKeyPhoneP2P + case privacyKeyProfilePhoto + case privacyKeyStatusTimestamp + case privacyKeyVoiceMessages + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .privacyKeyAddedByPhone: + if boxed { + buffer.appendInt32(1124062251) + } + + break + case .privacyKeyChatInvite: + if boxed { + buffer.appendInt32(1343122938) + } + + break + case .privacyKeyForwards: + if boxed { + buffer.appendInt32(1777096355) + } + + break + case .privacyKeyPhoneCall: + if boxed { + buffer.appendInt32(1030105979) + } + + break + case .privacyKeyPhoneNumber: + if boxed { + buffer.appendInt32(-778378131) + } + + break + case .privacyKeyPhoneP2P: + if boxed { + buffer.appendInt32(961092808) + } + + break + case .privacyKeyProfilePhoto: + if boxed { + buffer.appendInt32(-1777000467) + } + + break + case .privacyKeyStatusTimestamp: + if boxed { + buffer.appendInt32(-1137792208) + } + + break + case .privacyKeyVoiceMessages: + if boxed { + buffer.appendInt32(110621716) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .privacyKeyAddedByPhone: + return ("privacyKeyAddedByPhone", []) + case .privacyKeyChatInvite: + return ("privacyKeyChatInvite", []) + case .privacyKeyForwards: + return ("privacyKeyForwards", []) + case .privacyKeyPhoneCall: + return ("privacyKeyPhoneCall", []) + case .privacyKeyPhoneNumber: + return ("privacyKeyPhoneNumber", []) + case .privacyKeyPhoneP2P: + return ("privacyKeyPhoneP2P", []) + case .privacyKeyProfilePhoto: + return ("privacyKeyProfilePhoto", []) + case .privacyKeyStatusTimestamp: + return ("privacyKeyStatusTimestamp", []) + case .privacyKeyVoiceMessages: + return ("privacyKeyVoiceMessages", []) + } + } + + public static func parse_privacyKeyAddedByPhone(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyAddedByPhone + } + public static func parse_privacyKeyChatInvite(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyChatInvite + } + public static func parse_privacyKeyForwards(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyForwards + } + public static func parse_privacyKeyPhoneCall(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyPhoneCall + } + public static func parse_privacyKeyPhoneNumber(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyPhoneNumber + } + public static func parse_privacyKeyPhoneP2P(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyPhoneP2P + } + public static func parse_privacyKeyProfilePhoto(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyProfilePhoto + } + public static func parse_privacyKeyStatusTimestamp(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyStatusTimestamp + } + public static func parse_privacyKeyVoiceMessages(_ reader: BufferReader) -> PrivacyKey? { + return Api.PrivacyKey.privacyKeyVoiceMessages + } + + } +} +public extension Api { + enum PrivacyRule: TypeConstructorDescription { + case privacyValueAllowAll + case privacyValueAllowChatParticipants(chats: [Int64]) + case privacyValueAllowContacts + case privacyValueAllowUsers(users: [Int64]) + case privacyValueDisallowAll + case privacyValueDisallowChatParticipants(chats: [Int64]) + case privacyValueDisallowContacts + case privacyValueDisallowUsers(users: [Int64]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .privacyValueAllowAll: + if boxed { + buffer.appendInt32(1698855810) + } + + break + case .privacyValueAllowChatParticipants(let chats): + if boxed { + buffer.appendInt32(1796427406) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .privacyValueAllowContacts: + if boxed { + buffer.appendInt32(-123988) + } + + break + case .privacyValueAllowUsers(let users): + if boxed { + buffer.appendInt32(-1198497870) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .privacyValueDisallowAll: + if boxed { + buffer.appendInt32(-1955338397) + } + + break + case .privacyValueDisallowChatParticipants(let chats): + if boxed { + buffer.appendInt32(1103656293) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .privacyValueDisallowContacts: + if boxed { + buffer.appendInt32(-125240806) + } + + break + case .privacyValueDisallowUsers(let users): + if boxed { + buffer.appendInt32(-463335103) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .privacyValueAllowAll: + return ("privacyValueAllowAll", []) + case .privacyValueAllowChatParticipants(let chats): + return ("privacyValueAllowChatParticipants", [("chats", String(describing: chats))]) + case .privacyValueAllowContacts: + return ("privacyValueAllowContacts", []) + case .privacyValueAllowUsers(let users): + return ("privacyValueAllowUsers", [("users", String(describing: users))]) + case .privacyValueDisallowAll: + return ("privacyValueDisallowAll", []) + case .privacyValueDisallowChatParticipants(let chats): + return ("privacyValueDisallowChatParticipants", [("chats", String(describing: chats))]) + case .privacyValueDisallowContacts: + return ("privacyValueDisallowContacts", []) + case .privacyValueDisallowUsers(let users): + return ("privacyValueDisallowUsers", [("users", String(describing: users))]) + } + } + + public static func parse_privacyValueAllowAll(_ reader: BufferReader) -> PrivacyRule? { + return Api.PrivacyRule.privacyValueAllowAll + } + public static func parse_privacyValueAllowChatParticipants(_ reader: BufferReader) -> PrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PrivacyRule.privacyValueAllowChatParticipants(chats: _1!) + } + else { + return nil + } + } + public static func parse_privacyValueAllowContacts(_ reader: BufferReader) -> PrivacyRule? { + return Api.PrivacyRule.privacyValueAllowContacts + } + public static func parse_privacyValueAllowUsers(_ reader: BufferReader) -> PrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PrivacyRule.privacyValueAllowUsers(users: _1!) + } + else { + return nil + } + } + public static func parse_privacyValueDisallowAll(_ reader: BufferReader) -> PrivacyRule? { + return Api.PrivacyRule.privacyValueDisallowAll + } + public static func parse_privacyValueDisallowChatParticipants(_ reader: BufferReader) -> PrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PrivacyRule.privacyValueDisallowChatParticipants(chats: _1!) + } + else { + return nil + } + } + public static func parse_privacyValueDisallowContacts(_ reader: BufferReader) -> PrivacyRule? { + return Api.PrivacyRule.privacyValueDisallowContacts + } + public static func parse_privacyValueDisallowUsers(_ reader: BufferReader) -> PrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.PrivacyRule.privacyValueDisallowUsers(users: _1!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index bf6fb0bbfc..6fbc72af8f 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -1,16 +1,15 @@ public extension Api { - enum SearchResultsCalendarPeriod: TypeConstructorDescription { - case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32) + enum ReactionCount: TypeConstructorDescription { + case reactionCount(flags: Int32, reaction: String, count: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): + case .reactionCount(let flags, let reaction, let count): if boxed { - buffer.appendInt32(-911191137) + buffer.appendInt32(1873957073) } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(minMsgId, buffer: buffer, boxed: false) - serializeInt32(maxMsgId, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(reaction, buffer: buffer, boxed: false) serializeInt32(count, buffer: buffer, boxed: false) break } @@ -18,70 +17,23 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): - return ("searchResultsCalendarPeriod", [("date", String(describing: date)), ("minMsgId", String(describing: minMsgId)), ("maxMsgId", String(describing: maxMsgId)), ("count", String(describing: count))]) + case .reactionCount(let flags, let reaction, let count): + return ("reactionCount", [("flags", String(describing: flags)), ("reaction", String(describing: reaction)), ("count", String(describing: count))]) } } - public static func parse_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? { + public static func parse_reactionCount(_ reader: BufferReader) -> ReactionCount? { var _1: Int32? _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.SearchResultsCalendarPeriod.searchResultsCalendarPeriod(date: _1!, minMsgId: _2!, maxMsgId: _3!, count: _4!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SearchResultsPosition: TypeConstructorDescription { - case searchResultPosition(msgId: Int32, date: Int32, offset: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .searchResultPosition(let msgId, let date, let offset): - if boxed { - buffer.appendInt32(2137295719) - } - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(offset, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .searchResultPosition(let msgId, let date, let offset): - return ("searchResultPosition", [("msgId", String(describing: msgId)), ("date", String(describing: date)), ("offset", String(describing: offset))]) - } - } - - public static func parse_searchResultPosition(_ reader: BufferReader) -> SearchResultsPosition? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() + var _2: String? + _2 = parseString(reader) var _3: Int32? _3 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.SearchResultsPosition.searchResultPosition(msgId: _1!, date: _2!, offset: _3!) + return Api.ReactionCount.reactionCount(flags: _1!, reaction: _2!, count: _3!) } else { return nil @@ -91,41 +43,37 @@ public extension Api { } } public extension Api { - enum SecureCredentialsEncrypted: TypeConstructorDescription { - case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer) + enum ReceivedNotifyMessage: TypeConstructorDescription { + case receivedNotifyMessage(id: Int32, flags: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .secureCredentialsEncrypted(let data, let hash, let secret): + case .receivedNotifyMessage(let id, let flags): if boxed { - buffer.appendInt32(871426631) + buffer.appendInt32(-1551583367) } - serializeBytes(data, buffer: buffer, boxed: false) - serializeBytes(hash, buffer: buffer, boxed: false) - serializeBytes(secret, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .secureCredentialsEncrypted(let data, let hash, let secret): - return ("secureCredentialsEncrypted", [("data", String(describing: data)), ("hash", String(describing: hash)), ("secret", String(describing: secret))]) + case .receivedNotifyMessage(let id, let flags): + return ("receivedNotifyMessage", [("id", String(describing: id)), ("flags", String(describing: flags))]) } } - public static func parse_secureCredentialsEncrypted(_ reader: BufferReader) -> SecureCredentialsEncrypted? { - var _1: Buffer? - _1 = parseBytes(reader) - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Buffer? - _3 = parseBytes(reader) + public static func parse_receivedNotifyMessage(_ reader: BufferReader) -> ReceivedNotifyMessage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!) + if _c1 && _c2 { + return Api.ReceivedNotifyMessage.receivedNotifyMessage(id: _1!, flags: _2!) } else { return nil @@ -135,144 +83,333 @@ public extension Api { } } public extension Api { - enum SecureData: TypeConstructorDescription { - case secureData(data: Buffer, dataHash: Buffer, secret: Buffer) + enum RecentMeUrl: TypeConstructorDescription { + case recentMeUrlChat(url: String, chatId: Int64) + case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite) + case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered) + case recentMeUrlUnknown(url: String) + case recentMeUrlUser(url: String, userId: Int64) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .secureData(let data, let dataHash, let secret): + case .recentMeUrlChat(let url, let chatId): if boxed { - buffer.appendInt32(-1964327229) + buffer.appendInt32(-1294306862) } - serializeBytes(data, buffer: buffer, boxed: false) - serializeBytes(dataHash, buffer: buffer, boxed: false) - serializeBytes(secret, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(chatId, buffer: buffer, boxed: false) + break + case .recentMeUrlChatInvite(let url, let chatInvite): + if boxed { + buffer.appendInt32(-347535331) + } + serializeString(url, buffer: buffer, boxed: false) + chatInvite.serialize(buffer, true) + break + case .recentMeUrlStickerSet(let url, let set): + if boxed { + buffer.appendInt32(-1140172836) + } + serializeString(url, buffer: buffer, boxed: false) + set.serialize(buffer, true) + break + case .recentMeUrlUnknown(let url): + if boxed { + buffer.appendInt32(1189204285) + } + serializeString(url, buffer: buffer, boxed: false) + break + case .recentMeUrlUser(let url, let userId): + if boxed { + buffer.appendInt32(-1188296222) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .secureData(let data, let dataHash, let secret): - return ("secureData", [("data", String(describing: data)), ("dataHash", String(describing: dataHash)), ("secret", String(describing: secret))]) + case .recentMeUrlChat(let url, let chatId): + return ("recentMeUrlChat", [("url", String(describing: url)), ("chatId", String(describing: chatId))]) + case .recentMeUrlChatInvite(let url, let chatInvite): + return ("recentMeUrlChatInvite", [("url", String(describing: url)), ("chatInvite", String(describing: chatInvite))]) + case .recentMeUrlStickerSet(let url, let set): + return ("recentMeUrlStickerSet", [("url", String(describing: url)), ("set", String(describing: set))]) + case .recentMeUrlUnknown(let url): + return ("recentMeUrlUnknown", [("url", String(describing: url))]) + case .recentMeUrlUser(let url, let userId): + return ("recentMeUrlUser", [("url", String(describing: url)), ("userId", String(describing: userId))]) } } - public static func parse_secureData(_ reader: BufferReader) -> SecureData? { - var _1: Buffer? - _1 = parseBytes(reader) - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Buffer? - _3 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureData.secureData(data: _1!, dataHash: _2!, secret: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureFile: TypeConstructorDescription { - case secureFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer) - case secureFileEmpty - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret): - if boxed { - buffer.appendInt32(2097791614) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt64(size, buffer: buffer, boxed: false) - serializeInt32(dcId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeBytes(secret, buffer: buffer, boxed: false) - break - case .secureFileEmpty: - if boxed { - buffer.appendInt32(1679398724) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret): - return ("secureFile", [("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("size", String(describing: size)), ("dcId", String(describing: dcId)), ("date", String(describing: date)), ("fileHash", String(describing: fileHash)), ("secret", String(describing: secret))]) - case .secureFileEmpty: - return ("secureFileEmpty", []) - } - } - - public static func parse_secureFile(_ reader: BufferReader) -> SecureFile? { - var _1: Int64? - _1 = reader.readInt64() + public static func parse_recentMeUrlChat(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) var _2: Int64? _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Buffer? - _6 = parseBytes(reader) - var _7: Buffer? - _7 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.SecureFile.secureFile(id: _1!, accessHash: _2!, size: _3!, dcId: _4!, date: _5!, fileHash: _6!, secret: _7!) + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlChat(url: _1!, chatId: _2!) } else { return nil } } - public static func parse_secureFileEmpty(_ reader: BufferReader) -> SecureFile? { - return Api.SecureFile.secureFileEmpty + public static func parse_recentMeUrlChatInvite(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Api.ChatInvite? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.ChatInvite + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlChatInvite(url: _1!, chatInvite: _2!) + } + else { + return nil + } + } + public static func parse_recentMeUrlStickerSet(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Api.StickerSetCovered? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.StickerSetCovered + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlStickerSet(url: _1!, set: _2!) + } + else { + return nil + } + } + public static func parse_recentMeUrlUnknown(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.RecentMeUrl.recentMeUrlUnknown(url: _1!) + } + else { + return nil + } + } + public static func parse_recentMeUrlUser(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlUser(url: _1!, userId: _2!) + } + else { + return nil + } } } } public extension Api { - enum SecurePasswordKdfAlgo: TypeConstructorDescription { - case securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: Buffer) - case securePasswordKdfAlgoSHA512(salt: Buffer) - case securePasswordKdfAlgoUnknown + enum ReplyMarkup: TypeConstructorDescription { + case replyInlineMarkup(rows: [Api.KeyboardButtonRow]) + case replyKeyboardForceReply(flags: Int32, placeholder: String?) + case replyKeyboardHide(flags: Int32) + case replyKeyboardMarkup(flags: Int32, rows: [Api.KeyboardButtonRow], placeholder: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(let salt): + case .replyInlineMarkup(let rows): if boxed { - buffer.appendInt32(-1141711456) + buffer.appendInt32(1218642516) } - serializeBytes(salt, buffer: buffer, boxed: false) - break - case .securePasswordKdfAlgoSHA512(let salt): - if boxed { - buffer.appendInt32(-2042159726) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rows.count)) + for item in rows { + item.serialize(buffer, true) } - serializeBytes(salt, buffer: buffer, boxed: false) break - case .securePasswordKdfAlgoUnknown: + case .replyKeyboardForceReply(let flags, let placeholder): if boxed { - buffer.appendInt32(4883767) + buffer.appendInt32(-2035021048) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {serializeString(placeholder!, buffer: buffer, boxed: false)} + break + case .replyKeyboardHide(let flags): + if boxed { + buffer.appendInt32(-1606526075) + } + serializeInt32(flags, buffer: buffer, boxed: false) + break + case .replyKeyboardMarkup(let flags, let rows, let placeholder): + if boxed { + buffer.appendInt32(-2049074735) + } + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rows.count)) + for item in rows { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 3) != 0 {serializeString(placeholder!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .replyInlineMarkup(let rows): + return ("replyInlineMarkup", [("rows", String(describing: rows))]) + case .replyKeyboardForceReply(let flags, let placeholder): + return ("replyKeyboardForceReply", [("flags", String(describing: flags)), ("placeholder", String(describing: placeholder))]) + case .replyKeyboardHide(let flags): + return ("replyKeyboardHide", [("flags", String(describing: flags))]) + case .replyKeyboardMarkup(let flags, let rows, let placeholder): + return ("replyKeyboardMarkup", [("flags", String(describing: flags)), ("rows", String(describing: rows)), ("placeholder", String(describing: placeholder))]) + } + } + + public static func parse_replyInlineMarkup(_ reader: BufferReader) -> ReplyMarkup? { + var _1: [Api.KeyboardButtonRow]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButtonRow.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.ReplyMarkup.replyInlineMarkup(rows: _1!) + } + else { + return nil + } + } + public static func parse_replyKeyboardForceReply(_ reader: BufferReader) -> ReplyMarkup? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 3) != 0 {_2 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil + if _c1 && _c2 { + return Api.ReplyMarkup.replyKeyboardForceReply(flags: _1!, placeholder: _2) + } + else { + return nil + } + } + public static func parse_replyKeyboardHide(_ reader: BufferReader) -> ReplyMarkup? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.ReplyMarkup.replyKeyboardHide(flags: _1!) + } + else { + return nil + } + } + public static func parse_replyKeyboardMarkup(_ reader: BufferReader) -> ReplyMarkup? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.KeyboardButtonRow]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButtonRow.self) + } + var _3: String? + if Int(_1!) & Int(1 << 3) != 0 {_3 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.ReplyMarkup.replyKeyboardMarkup(flags: _1!, rows: _2!, placeholder: _3) + } + else { + return nil + } + } + + } +} +public extension Api { + enum ReportReason: TypeConstructorDescription { + case inputReportReasonChildAbuse + case inputReportReasonCopyright + case inputReportReasonFake + case inputReportReasonGeoIrrelevant + case inputReportReasonIllegalDrugs + case inputReportReasonOther + case inputReportReasonPersonalDetails + case inputReportReasonPornography + case inputReportReasonSpam + case inputReportReasonViolence + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputReportReasonChildAbuse: + if boxed { + buffer.appendInt32(-1376497949) + } + + break + case .inputReportReasonCopyright: + if boxed { + buffer.appendInt32(-1685456582) + } + + break + case .inputReportReasonFake: + if boxed { + buffer.appendInt32(-170010905) + } + + break + case .inputReportReasonGeoIrrelevant: + if boxed { + buffer.appendInt32(-606798099) + } + + break + case .inputReportReasonIllegalDrugs: + if boxed { + buffer.appendInt32(177124030) + } + + break + case .inputReportReasonOther: + if boxed { + buffer.appendInt32(-1041980751) + } + + break + case .inputReportReasonPersonalDetails: + if boxed { + buffer.appendInt32(-1631091139) + } + + break + case .inputReportReasonPornography: + if boxed { + buffer.appendInt32(777640226) + } + + break + case .inputReportReasonSpam: + if boxed { + buffer.appendInt32(1490799288) + } + + break + case .inputReportReasonViolence: + if boxed { + buffer.appendInt32(505595789) } break @@ -281,205 +418,484 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(let salt): - return ("securePasswordKdfAlgoPBKDF2HMACSHA512iter100000", [("salt", String(describing: salt))]) - case .securePasswordKdfAlgoSHA512(let salt): - return ("securePasswordKdfAlgoSHA512", [("salt", String(describing: salt))]) - case .securePasswordKdfAlgoUnknown: - return ("securePasswordKdfAlgoUnknown", []) + case .inputReportReasonChildAbuse: + return ("inputReportReasonChildAbuse", []) + case .inputReportReasonCopyright: + return ("inputReportReasonCopyright", []) + case .inputReportReasonFake: + return ("inputReportReasonFake", []) + case .inputReportReasonGeoIrrelevant: + return ("inputReportReasonGeoIrrelevant", []) + case .inputReportReasonIllegalDrugs: + return ("inputReportReasonIllegalDrugs", []) + case .inputReportReasonOther: + return ("inputReportReasonOther", []) + case .inputReportReasonPersonalDetails: + return ("inputReportReasonPersonalDetails", []) + case .inputReportReasonPornography: + return ("inputReportReasonPornography", []) + case .inputReportReasonSpam: + return ("inputReportReasonSpam", []) + case .inputReportReasonViolence: + return ("inputReportReasonViolence", []) } } - public static func parse_securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: _1!) - } - else { - return nil - } + public static func parse_inputReportReasonChildAbuse(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonChildAbuse } - public static func parse_securePasswordKdfAlgoSHA512(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoSHA512(salt: _1!) - } - else { - return nil - } + public static func parse_inputReportReasonCopyright(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonCopyright } - public static func parse_securePasswordKdfAlgoUnknown(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { - return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoUnknown + public static func parse_inputReportReasonFake(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonFake + } + public static func parse_inputReportReasonGeoIrrelevant(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonGeoIrrelevant + } + public static func parse_inputReportReasonIllegalDrugs(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonIllegalDrugs + } + public static func parse_inputReportReasonOther(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonOther + } + public static func parse_inputReportReasonPersonalDetails(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonPersonalDetails + } + public static func parse_inputReportReasonPornography(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonPornography + } + public static func parse_inputReportReasonSpam(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonSpam + } + public static func parse_inputReportReasonViolence(_ reader: BufferReader) -> ReportReason? { + return Api.ReportReason.inputReportReasonViolence } } } public extension Api { - enum SecurePlainData: TypeConstructorDescription { - case securePlainEmail(email: String) - case securePlainPhone(phone: String) + enum RestrictionReason: TypeConstructorDescription { + case restrictionReason(platform: String, reason: String, text: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .securePlainEmail(let email): + case .restrictionReason(let platform, let reason, let text): if boxed { - buffer.appendInt32(569137759) + buffer.appendInt32(-797791052) } + serializeString(platform, buffer: buffer, boxed: false) + serializeString(reason, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .restrictionReason(let platform, let reason, let text): + return ("restrictionReason", [("platform", String(describing: platform)), ("reason", String(describing: reason)), ("text", String(describing: text))]) + } + } + + public static func parse_restrictionReason(_ reader: BufferReader) -> RestrictionReason? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.RestrictionReason.restrictionReason(platform: _1!, reason: _2!, text: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + indirect enum RichText: TypeConstructorDescription { + case textAnchor(text: Api.RichText, name: String) + case textBold(text: Api.RichText) + case textConcat(texts: [Api.RichText]) + case textEmail(text: Api.RichText, email: String) + case textEmpty + case textFixed(text: Api.RichText) + case textImage(documentId: Int64, w: Int32, h: Int32) + case textItalic(text: Api.RichText) + case textMarked(text: Api.RichText) + case textPhone(text: Api.RichText, phone: String) + case textPlain(text: String) + case textStrike(text: Api.RichText) + case textSubscript(text: Api.RichText) + case textSuperscript(text: Api.RichText) + case textUnderline(text: Api.RichText) + case textUrl(text: Api.RichText, url: String, webpageId: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .textAnchor(let text, let name): + if boxed { + buffer.appendInt32(894777186) + } + text.serialize(buffer, true) + serializeString(name, buffer: buffer, boxed: false) + break + case .textBold(let text): + if boxed { + buffer.appendInt32(1730456516) + } + text.serialize(buffer, true) + break + case .textConcat(let texts): + if boxed { + buffer.appendInt32(2120376535) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(texts.count)) + for item in texts { + item.serialize(buffer, true) + } + break + case .textEmail(let text, let email): + if boxed { + buffer.appendInt32(-564523562) + } + text.serialize(buffer, true) serializeString(email, buffer: buffer, boxed: false) break - case .securePlainPhone(let phone): + case .textEmpty: if boxed { - buffer.appendInt32(2103482845) + buffer.appendInt32(-599948721) } + + break + case .textFixed(let text): + if boxed { + buffer.appendInt32(1816074681) + } + text.serialize(buffer, true) + break + case .textImage(let documentId, let w, let h): + if boxed { + buffer.appendInt32(136105807) + } + serializeInt64(documentId, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + break + case .textItalic(let text): + if boxed { + buffer.appendInt32(-653089380) + } + text.serialize(buffer, true) + break + case .textMarked(let text): + if boxed { + buffer.appendInt32(55281185) + } + text.serialize(buffer, true) + break + case .textPhone(let text, let phone): + if boxed { + buffer.appendInt32(483104362) + } + text.serialize(buffer, true) serializeString(phone, buffer: buffer, boxed: false) break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .securePlainEmail(let email): - return ("securePlainEmail", [("email", String(describing: email))]) - case .securePlainPhone(let phone): - return ("securePlainPhone", [("phone", String(describing: phone))]) - } - } - - public static func parse_securePlainEmail(_ reader: BufferReader) -> SecurePlainData? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SecurePlainData.securePlainEmail(email: _1!) - } - else { - return nil - } - } - public static func parse_securePlainPhone(_ reader: BufferReader) -> SecurePlainData? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SecurePlainData.securePlainPhone(phone: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureRequiredType: TypeConstructorDescription { - case secureRequiredType(flags: Int32, type: Api.SecureValueType) - case secureRequiredTypeOneOf(types: [Api.SecureRequiredType]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureRequiredType(let flags, let type): + case .textPlain(let text): if boxed { - buffer.appendInt32(-2103600678) + buffer.appendInt32(1950782688) } - serializeInt32(flags, buffer: buffer, boxed: false) - type.serialize(buffer, true) + serializeString(text, buffer: buffer, boxed: false) break - case .secureRequiredTypeOneOf(let types): + case .textStrike(let text): if boxed { - buffer.appendInt32(41187252) + buffer.appendInt32(-1678197867) } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(types.count)) - for item in types { - item.serialize(buffer, true) + text.serialize(buffer, true) + break + case .textSubscript(let text): + if boxed { + buffer.appendInt32(-311786236) } + text.serialize(buffer, true) + break + case .textSuperscript(let text): + if boxed { + buffer.appendInt32(-939827711) + } + text.serialize(buffer, true) + break + case .textUnderline(let text): + if boxed { + buffer.appendInt32(-1054465340) + } + text.serialize(buffer, true) + break + case .textUrl(let text, let url, let webpageId): + if boxed { + buffer.appendInt32(1009288385) + } + text.serialize(buffer, true) + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(webpageId, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .secureRequiredType(let flags, let type): - return ("secureRequiredType", [("flags", String(describing: flags)), ("type", String(describing: type))]) - case .secureRequiredTypeOneOf(let types): - return ("secureRequiredTypeOneOf", [("types", String(describing: types))]) + case .textAnchor(let text, let name): + return ("textAnchor", [("text", String(describing: text)), ("name", String(describing: name))]) + case .textBold(let text): + return ("textBold", [("text", String(describing: text))]) + case .textConcat(let texts): + return ("textConcat", [("texts", String(describing: texts))]) + case .textEmail(let text, let email): + return ("textEmail", [("text", String(describing: text)), ("email", String(describing: email))]) + case .textEmpty: + return ("textEmpty", []) + case .textFixed(let text): + return ("textFixed", [("text", String(describing: text))]) + case .textImage(let documentId, let w, let h): + return ("textImage", [("documentId", String(describing: documentId)), ("w", String(describing: w)), ("h", String(describing: h))]) + case .textItalic(let text): + return ("textItalic", [("text", String(describing: text))]) + case .textMarked(let text): + return ("textMarked", [("text", String(describing: text))]) + case .textPhone(let text, let phone): + return ("textPhone", [("text", String(describing: text)), ("phone", String(describing: phone))]) + case .textPlain(let text): + return ("textPlain", [("text", String(describing: text))]) + case .textStrike(let text): + return ("textStrike", [("text", String(describing: text))]) + case .textSubscript(let text): + return ("textSubscript", [("text", String(describing: text))]) + case .textSuperscript(let text): + return ("textSuperscript", [("text", String(describing: text))]) + case .textUnderline(let text): + return ("textUnderline", [("text", String(describing: text))]) + case .textUrl(let text, let url, let webpageId): + return ("textUrl", [("text", String(describing: text)), ("url", String(describing: url)), ("webpageId", String(describing: webpageId))]) } } - public static func parse_secureRequiredType(_ reader: BufferReader) -> SecureRequiredType? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.SecureValueType? + public static func parse_textAnchor(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.SecureValueType + _1 = Api.parse(reader, signature: signature) as? Api.RichText } + var _2: String? + _2 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.SecureRequiredType.secureRequiredType(flags: _1!, type: _2!) + return Api.RichText.textAnchor(text: _1!, name: _2!) } else { return nil } } - public static func parse_secureRequiredTypeOneOf(_ reader: BufferReader) -> SecureRequiredType? { - var _1: [Api.SecureRequiredType]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureRequiredType.self) + public static func parse_textBold(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText } let _c1 = _1 != nil if _c1 { - return Api.SecureRequiredType.secureRequiredTypeOneOf(types: _1!) + return Api.RichText.textBold(text: _1!) } else { return nil } } - - } -} -public extension Api { - enum SecureSecretSettings: TypeConstructorDescription { - case secureSecretSettings(secureAlgo: Api.SecurePasswordKdfAlgo, secureSecret: Buffer, secureSecretId: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureSecretSettings(let secureAlgo, let secureSecret, let secureSecretId): - if boxed { - buffer.appendInt32(354925740) - } - secureAlgo.serialize(buffer, true) - serializeBytes(secureSecret, buffer: buffer, boxed: false) - serializeInt64(secureSecretId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureSecretSettings(let secureAlgo, let secureSecret, let secureSecretId): - return ("secureSecretSettings", [("secureAlgo", String(describing: secureAlgo)), ("secureSecret", String(describing: secureSecret)), ("secureSecretId", String(describing: secureSecretId))]) - } - } - - public static func parse_secureSecretSettings(_ reader: BufferReader) -> SecureSecretSettings? { - var _1: Api.SecurePasswordKdfAlgo? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecurePasswordKdfAlgo + public static func parse_textConcat(_ reader: BufferReader) -> RichText? { + var _1: [Api.RichText]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RichText.self) } - var _2: Buffer? - _2 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textConcat(texts: _1!) + } + else { + return nil + } + } + public static func parse_textEmail(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RichText.textEmail(text: _1!, email: _2!) + } + else { + return nil + } + } + public static func parse_textEmpty(_ reader: BufferReader) -> RichText? { + return Api.RichText.textEmpty + } + public static func parse_textFixed(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textFixed(text: _1!) + } + else { + return nil + } + } + public static func parse_textImage(_ reader: BufferReader) -> RichText? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.RichText.textImage(documentId: _1!, w: _2!, h: _3!) + } + else { + return nil + } + } + public static func parse_textItalic(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textItalic(text: _1!) + } + else { + return nil + } + } + public static func parse_textMarked(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textMarked(text: _1!) + } + else { + return nil + } + } + public static func parse_textPhone(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RichText.textPhone(text: _1!, phone: _2!) + } + else { + return nil + } + } + public static func parse_textPlain(_ reader: BufferReader) -> RichText? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textPlain(text: _1!) + } + else { + return nil + } + } + public static func parse_textStrike(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textStrike(text: _1!) + } + else { + return nil + } + } + public static func parse_textSubscript(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textSubscript(text: _1!) + } + else { + return nil + } + } + public static func parse_textSuperscript(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textSuperscript(text: _1!) + } + else { + return nil + } + } + public static func parse_textUnderline(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + let _c1 = _1 != nil + if _c1 { + return Api.RichText.textUnderline(text: _1!) + } + else { + return nil + } + } + public static func parse_textUrl(_ reader: BufferReader) -> RichText? { + var _1: Api.RichText? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.RichText + } + var _2: String? + _2 = parseString(reader) var _3: Int64? _3 = reader.readInt64() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.SecureSecretSettings.secureSecretSettings(secureAlgo: _1!, secureSecret: _2!, secureSecretId: _3!) + return Api.RichText.textUrl(text: _1!, url: _2!, webpageId: _3!) } else { return nil @@ -488,615 +904,3 @@ public extension Api { } } -public extension Api { - enum SecureValue: TypeConstructorDescription { - case secureValue(flags: Int32, type: Api.SecureValueType, data: Api.SecureData?, frontSide: Api.SecureFile?, reverseSide: Api.SecureFile?, selfie: Api.SecureFile?, translation: [Api.SecureFile]?, files: [Api.SecureFile]?, plainData: Api.SecurePlainData?, hash: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureValue(let flags, let type, let data, let frontSide, let reverseSide, let selfie, let translation, let files, let plainData, let hash): - if boxed { - buffer.appendInt32(411017418) - } - serializeInt32(flags, buffer: buffer, boxed: false) - type.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {data!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {frontSide!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {reverseSide!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {selfie!.serialize(buffer, true)} - if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(translation!.count)) - for item in translation! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(files!.count)) - for item in files! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 5) != 0 {plainData!.serialize(buffer, true)} - serializeBytes(hash, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureValue(let flags, let type, let data, let frontSide, let reverseSide, let selfie, let translation, let files, let plainData, let hash): - return ("secureValue", [("flags", String(describing: flags)), ("type", String(describing: type)), ("data", String(describing: data)), ("frontSide", String(describing: frontSide)), ("reverseSide", String(describing: reverseSide)), ("selfie", String(describing: selfie)), ("translation", String(describing: translation)), ("files", String(describing: files)), ("plainData", String(describing: plainData)), ("hash", String(describing: hash))]) - } - } - - public static func parse_secureValue(_ reader: BufferReader) -> SecureValue? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.SecureValueType? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _3: Api.SecureData? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.SecureData - } } - var _4: Api.SecureFile? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.SecureFile - } } - var _5: Api.SecureFile? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.SecureFile - } } - var _6: Api.SecureFile? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.SecureFile - } } - var _7: [Api.SecureFile]? - if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureFile.self) - } } - var _8: [Api.SecureFile]? - if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { - _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureFile.self) - } } - var _9: Api.SecurePlainData? - if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.SecurePlainData - } } - var _10: Buffer? - _10 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 5) == 0) || _9 != nil - let _c10 = _10 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { - return Api.SecureValue.secureValue(flags: _1!, type: _2!, data: _3, frontSide: _4, reverseSide: _5, selfie: _6, translation: _7, files: _8, plainData: _9, hash: _10!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureValueError: TypeConstructorDescription { - case secureValueError(type: Api.SecureValueType, hash: Buffer, text: String) - case secureValueErrorData(type: Api.SecureValueType, dataHash: Buffer, field: String, text: String) - case secureValueErrorFile(type: Api.SecureValueType, fileHash: Buffer, text: String) - case secureValueErrorFiles(type: Api.SecureValueType, fileHash: [Buffer], text: String) - case secureValueErrorFrontSide(type: Api.SecureValueType, fileHash: Buffer, text: String) - case secureValueErrorReverseSide(type: Api.SecureValueType, fileHash: Buffer, text: String) - case secureValueErrorSelfie(type: Api.SecureValueType, fileHash: Buffer, text: String) - case secureValueErrorTranslationFile(type: Api.SecureValueType, fileHash: Buffer, text: String) - case secureValueErrorTranslationFiles(type: Api.SecureValueType, fileHash: [Buffer], text: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureValueError(let type, let hash, let text): - if boxed { - buffer.appendInt32(-2036501105) - } - type.serialize(buffer, true) - serializeBytes(hash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorData(let type, let dataHash, let field, let text): - if boxed { - buffer.appendInt32(-391902247) - } - type.serialize(buffer, true) - serializeBytes(dataHash, buffer: buffer, boxed: false) - serializeString(field, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorFile(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(2054162547) - } - type.serialize(buffer, true) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorFiles(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(1717706985) - } - type.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(fileHash.count)) - for item in fileHash { - serializeBytes(item, buffer: buffer, boxed: false) - } - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorFrontSide(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(12467706) - } - type.serialize(buffer, true) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorReverseSide(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(-2037765467) - } - type.serialize(buffer, true) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorSelfie(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(-449327402) - } - type.serialize(buffer, true) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorTranslationFile(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(-1592506512) - } - type.serialize(buffer, true) - serializeBytes(fileHash, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .secureValueErrorTranslationFiles(let type, let fileHash, let text): - if boxed { - buffer.appendInt32(878931416) - } - type.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(fileHash.count)) - for item in fileHash { - serializeBytes(item, buffer: buffer, boxed: false) - } - serializeString(text, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureValueError(let type, let hash, let text): - return ("secureValueError", [("type", String(describing: type)), ("hash", String(describing: hash)), ("text", String(describing: text))]) - case .secureValueErrorData(let type, let dataHash, let field, let text): - return ("secureValueErrorData", [("type", String(describing: type)), ("dataHash", String(describing: dataHash)), ("field", String(describing: field)), ("text", String(describing: text))]) - case .secureValueErrorFile(let type, let fileHash, let text): - return ("secureValueErrorFile", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorFiles(let type, let fileHash, let text): - return ("secureValueErrorFiles", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorFrontSide(let type, let fileHash, let text): - return ("secureValueErrorFrontSide", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorReverseSide(let type, let fileHash, let text): - return ("secureValueErrorReverseSide", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorSelfie(let type, let fileHash, let text): - return ("secureValueErrorSelfie", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorTranslationFile(let type, let fileHash, let text): - return ("secureValueErrorTranslationFile", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - case .secureValueErrorTranslationFiles(let type, let fileHash, let text): - return ("secureValueErrorTranslationFiles", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) - } - } - - public static func parse_secureValueError(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueError(type: _1!, hash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorData(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.SecureValueError.secureValueErrorData(type: _1!, dataHash: _2!, field: _3!, text: _4!) - } - else { - return nil - } - } - public static func parse_secureValueErrorFile(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorFile(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorFiles(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: [Buffer]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) - } - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorFiles(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorFrontSide(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorFrontSide(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorReverseSide(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorReverseSide(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorSelfie(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorSelfie(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorTranslationFile(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorTranslationFile(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - public static func parse_secureValueErrorTranslationFiles(_ reader: BufferReader) -> SecureValueError? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: [Buffer]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) - } - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureValueError.secureValueErrorTranslationFiles(type: _1!, fileHash: _2!, text: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureValueHash: TypeConstructorDescription { - case secureValueHash(type: Api.SecureValueType, hash: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureValueHash(let type, let hash): - if boxed { - buffer.appendInt32(-316748368) - } - type.serialize(buffer, true) - serializeBytes(hash, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureValueHash(let type, let hash): - return ("secureValueHash", [("type", String(describing: type)), ("hash", String(describing: hash))]) - } - } - - public static func parse_secureValueHash(_ reader: BufferReader) -> SecureValueHash? { - var _1: Api.SecureValueType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType - } - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.SecureValueHash.secureValueHash(type: _1!, hash: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureValueType: TypeConstructorDescription { - case secureValueTypeAddress - case secureValueTypeBankStatement - case secureValueTypeDriverLicense - case secureValueTypeEmail - case secureValueTypeIdentityCard - case secureValueTypeInternalPassport - case secureValueTypePassport - case secureValueTypePassportRegistration - case secureValueTypePersonalDetails - case secureValueTypePhone - case secureValueTypeRentalAgreement - case secureValueTypeTemporaryRegistration - case secureValueTypeUtilityBill - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureValueTypeAddress: - if boxed { - buffer.appendInt32(-874308058) - } - - break - case .secureValueTypeBankStatement: - if boxed { - buffer.appendInt32(-1995211763) - } - - break - case .secureValueTypeDriverLicense: - if boxed { - buffer.appendInt32(115615172) - } - - break - case .secureValueTypeEmail: - if boxed { - buffer.appendInt32(-1908627474) - } - - break - case .secureValueTypeIdentityCard: - if boxed { - buffer.appendInt32(-1596951477) - } - - break - case .secureValueTypeInternalPassport: - if boxed { - buffer.appendInt32(-1717268701) - } - - break - case .secureValueTypePassport: - if boxed { - buffer.appendInt32(1034709504) - } - - break - case .secureValueTypePassportRegistration: - if boxed { - buffer.appendInt32(-1713143702) - } - - break - case .secureValueTypePersonalDetails: - if boxed { - buffer.appendInt32(-1658158621) - } - - break - case .secureValueTypePhone: - if boxed { - buffer.appendInt32(-1289704741) - } - - break - case .secureValueTypeRentalAgreement: - if boxed { - buffer.appendInt32(-1954007928) - } - - break - case .secureValueTypeTemporaryRegistration: - if boxed { - buffer.appendInt32(-368907213) - } - - break - case .secureValueTypeUtilityBill: - if boxed { - buffer.appendInt32(-63531698) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .secureValueTypeAddress: - return ("secureValueTypeAddress", []) - case .secureValueTypeBankStatement: - return ("secureValueTypeBankStatement", []) - case .secureValueTypeDriverLicense: - return ("secureValueTypeDriverLicense", []) - case .secureValueTypeEmail: - return ("secureValueTypeEmail", []) - case .secureValueTypeIdentityCard: - return ("secureValueTypeIdentityCard", []) - case .secureValueTypeInternalPassport: - return ("secureValueTypeInternalPassport", []) - case .secureValueTypePassport: - return ("secureValueTypePassport", []) - case .secureValueTypePassportRegistration: - return ("secureValueTypePassportRegistration", []) - case .secureValueTypePersonalDetails: - return ("secureValueTypePersonalDetails", []) - case .secureValueTypePhone: - return ("secureValueTypePhone", []) - case .secureValueTypeRentalAgreement: - return ("secureValueTypeRentalAgreement", []) - case .secureValueTypeTemporaryRegistration: - return ("secureValueTypeTemporaryRegistration", []) - case .secureValueTypeUtilityBill: - return ("secureValueTypeUtilityBill", []) - } - } - - public static func parse_secureValueTypeAddress(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeAddress - } - public static func parse_secureValueTypeBankStatement(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeBankStatement - } - public static func parse_secureValueTypeDriverLicense(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeDriverLicense - } - public static func parse_secureValueTypeEmail(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeEmail - } - public static func parse_secureValueTypeIdentityCard(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeIdentityCard - } - public static func parse_secureValueTypeInternalPassport(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeInternalPassport - } - public static func parse_secureValueTypePassport(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypePassport - } - public static func parse_secureValueTypePassportRegistration(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypePassportRegistration - } - public static func parse_secureValueTypePersonalDetails(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypePersonalDetails - } - public static func parse_secureValueTypePhone(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypePhone - } - public static func parse_secureValueTypeRentalAgreement(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeRentalAgreement - } - public static func parse_secureValueTypeTemporaryRegistration(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeTemporaryRegistration - } - public static func parse_secureValueTypeUtilityBill(_ reader: BufferReader) -> SecureValueType? { - return Api.SecureValueType.secureValueTypeUtilityBill - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api18.swift b/submodules/TelegramApi/Sources/Api18.swift index 8e3e101b48..c76b5fa753 100644 --- a/submodules/TelegramApi/Sources/Api18.swift +++ b/submodules/TelegramApi/Sources/Api18.swift @@ -1,351 +1,43 @@ public extension Api { - enum SendMessageAction: TypeConstructorDescription { - case sendMessageCancelAction - case sendMessageChooseContactAction - case sendMessageChooseStickerAction - case sendMessageEmojiInteraction(emoticon: String, msgId: Int32, interaction: Api.DataJSON) - case sendMessageEmojiInteractionSeen(emoticon: String) - case sendMessageGamePlayAction - case sendMessageGeoLocationAction - case sendMessageHistoryImportAction(progress: Int32) - case sendMessageRecordAudioAction - case sendMessageRecordRoundAction - case sendMessageRecordVideoAction - case sendMessageTypingAction - case sendMessageUploadAudioAction(progress: Int32) - case sendMessageUploadDocumentAction(progress: Int32) - case sendMessageUploadPhotoAction(progress: Int32) - case sendMessageUploadRoundAction(progress: Int32) - case sendMessageUploadVideoAction(progress: Int32) - case speakingInGroupCallAction + enum SavedContact: TypeConstructorDescription { + case savedPhoneContact(phone: String, firstName: String, lastName: String, date: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .sendMessageCancelAction: + case .savedPhoneContact(let phone, let firstName, let lastName, let date): if boxed { - buffer.appendInt32(-44119819) + buffer.appendInt32(289586518) } - - break - case .sendMessageChooseContactAction: - if boxed { - buffer.appendInt32(1653390447) - } - - break - case .sendMessageChooseStickerAction: - if boxed { - buffer.appendInt32(-1336228175) - } - - break - case .sendMessageEmojiInteraction(let emoticon, let msgId, let interaction): - if boxed { - buffer.appendInt32(630664139) - } - serializeString(emoticon, buffer: buffer, boxed: false) - serializeInt32(msgId, buffer: buffer, boxed: false) - interaction.serialize(buffer, true) - break - case .sendMessageEmojiInteractionSeen(let emoticon): - if boxed { - buffer.appendInt32(-1234857938) - } - serializeString(emoticon, buffer: buffer, boxed: false) - break - case .sendMessageGamePlayAction: - if boxed { - buffer.appendInt32(-580219064) - } - - break - case .sendMessageGeoLocationAction: - if boxed { - buffer.appendInt32(393186209) - } - - break - case .sendMessageHistoryImportAction(let progress): - if boxed { - buffer.appendInt32(-606432698) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .sendMessageRecordAudioAction: - if boxed { - buffer.appendInt32(-718310409) - } - - break - case .sendMessageRecordRoundAction: - if boxed { - buffer.appendInt32(-1997373508) - } - - break - case .sendMessageRecordVideoAction: - if boxed { - buffer.appendInt32(-1584933265) - } - - break - case .sendMessageTypingAction: - if boxed { - buffer.appendInt32(381645902) - } - - break - case .sendMessageUploadAudioAction(let progress): - if boxed { - buffer.appendInt32(-212740181) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .sendMessageUploadDocumentAction(let progress): - if boxed { - buffer.appendInt32(-1441998364) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .sendMessageUploadPhotoAction(let progress): - if boxed { - buffer.appendInt32(-774682074) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .sendMessageUploadRoundAction(let progress): - if boxed { - buffer.appendInt32(608050278) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .sendMessageUploadVideoAction(let progress): - if boxed { - buffer.appendInt32(-378127636) - } - serializeInt32(progress, buffer: buffer, boxed: false) - break - case .speakingInGroupCallAction: - if boxed { - buffer.appendInt32(-651419003) - } - + serializeString(phone, buffer: buffer, boxed: false) + serializeString(firstName, buffer: buffer, boxed: false) + serializeString(lastName, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .sendMessageCancelAction: - return ("sendMessageCancelAction", []) - case .sendMessageChooseContactAction: - return ("sendMessageChooseContactAction", []) - case .sendMessageChooseStickerAction: - return ("sendMessageChooseStickerAction", []) - case .sendMessageEmojiInteraction(let emoticon, let msgId, let interaction): - return ("sendMessageEmojiInteraction", [("emoticon", String(describing: emoticon)), ("msgId", String(describing: msgId)), ("interaction", String(describing: interaction))]) - case .sendMessageEmojiInteractionSeen(let emoticon): - return ("sendMessageEmojiInteractionSeen", [("emoticon", String(describing: emoticon))]) - case .sendMessageGamePlayAction: - return ("sendMessageGamePlayAction", []) - case .sendMessageGeoLocationAction: - return ("sendMessageGeoLocationAction", []) - case .sendMessageHistoryImportAction(let progress): - return ("sendMessageHistoryImportAction", [("progress", String(describing: progress))]) - case .sendMessageRecordAudioAction: - return ("sendMessageRecordAudioAction", []) - case .sendMessageRecordRoundAction: - return ("sendMessageRecordRoundAction", []) - case .sendMessageRecordVideoAction: - return ("sendMessageRecordVideoAction", []) - case .sendMessageTypingAction: - return ("sendMessageTypingAction", []) - case .sendMessageUploadAudioAction(let progress): - return ("sendMessageUploadAudioAction", [("progress", String(describing: progress))]) - case .sendMessageUploadDocumentAction(let progress): - return ("sendMessageUploadDocumentAction", [("progress", String(describing: progress))]) - case .sendMessageUploadPhotoAction(let progress): - return ("sendMessageUploadPhotoAction", [("progress", String(describing: progress))]) - case .sendMessageUploadRoundAction(let progress): - return ("sendMessageUploadRoundAction", [("progress", String(describing: progress))]) - case .sendMessageUploadVideoAction(let progress): - return ("sendMessageUploadVideoAction", [("progress", String(describing: progress))]) - case .speakingInGroupCallAction: - return ("speakingInGroupCallAction", []) + case .savedPhoneContact(let phone, let firstName, let lastName, let date): + return ("savedPhoneContact", [("phone", String(describing: phone)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("date", String(describing: date))]) } } - public static func parse_sendMessageCancelAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageCancelAction - } - public static func parse_sendMessageChooseContactAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageChooseContactAction - } - public static func parse_sendMessageChooseStickerAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageChooseStickerAction - } - public static func parse_sendMessageEmojiInteraction(_ reader: BufferReader) -> SendMessageAction? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.DataJSON? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SendMessageAction.sendMessageEmojiInteraction(emoticon: _1!, msgId: _2!, interaction: _3!) - } - else { - return nil - } - } - public static func parse_sendMessageEmojiInteractionSeen(_ reader: BufferReader) -> SendMessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageEmojiInteractionSeen(emoticon: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageGamePlayAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageGamePlayAction - } - public static func parse_sendMessageGeoLocationAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageGeoLocationAction - } - public static func parse_sendMessageHistoryImportAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageHistoryImportAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageRecordAudioAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageRecordAudioAction - } - public static func parse_sendMessageRecordRoundAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageRecordRoundAction - } - public static func parse_sendMessageRecordVideoAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageRecordVideoAction - } - public static func parse_sendMessageTypingAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.sendMessageTypingAction - } - public static func parse_sendMessageUploadAudioAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageUploadAudioAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageUploadDocumentAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageUploadDocumentAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageUploadPhotoAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageUploadPhotoAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageUploadRoundAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageUploadRoundAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_sendMessageUploadVideoAction(_ reader: BufferReader) -> SendMessageAction? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.SendMessageAction.sendMessageUploadVideoAction(progress: _1!) - } - else { - return nil - } - } - public static func parse_speakingInGroupCallAction(_ reader: BufferReader) -> SendMessageAction? { - return Api.SendMessageAction.speakingInGroupCallAction - } - - } -} -public extension Api { - enum ShippingOption: TypeConstructorDescription { - case shippingOption(id: String, title: String, prices: [Api.LabeledPrice]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .shippingOption(let id, let title, let prices): - if boxed { - buffer.appendInt32(-1239335713) - } - serializeString(id, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(prices.count)) - for item in prices { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .shippingOption(let id, let title, let prices): - return ("shippingOption", [("id", String(describing: id)), ("title", String(describing: title)), ("prices", String(describing: prices))]) - } - } - - public static func parse_shippingOption(_ reader: BufferReader) -> ShippingOption? { + public static func parse_savedPhoneContact(_ reader: BufferReader) -> SavedContact? { var _1: String? _1 = parseString(reader) var _2: String? _2 = parseString(reader) - var _3: [Api.LabeledPrice]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LabeledPrice.self) - } + var _3: String? + _3 = parseString(reader) + var _4: Int32? + _4 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.ShippingOption.shippingOption(id: _1!, title: _2!, prices: _3!) + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.SavedContact.savedPhoneContact(phone: _1!, firstName: _2!, lastName: _3!, date: _4!) } else { return nil @@ -355,313 +47,33 @@ public extension Api { } } public extension Api { - enum SimpleWebViewResult: TypeConstructorDescription { - case simpleWebViewResultUrl(url: String) + enum SearchResultsCalendarPeriod: TypeConstructorDescription { + case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .simpleWebViewResultUrl(let url): + case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): if boxed { - buffer.appendInt32(-2010155333) + buffer.appendInt32(-911191137) } - serializeString(url, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(minMsgId, buffer: buffer, boxed: false) + serializeInt32(maxMsgId, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .simpleWebViewResultUrl(let url): - return ("simpleWebViewResultUrl", [("url", String(describing: url))]) + case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): + return ("searchResultsCalendarPeriod", [("date", String(describing: date)), ("minMsgId", String(describing: minMsgId)), ("maxMsgId", String(describing: maxMsgId)), ("count", String(describing: count))]) } } - public static func parse_simpleWebViewResultUrl(_ reader: BufferReader) -> SimpleWebViewResult? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.SimpleWebViewResult.simpleWebViewResultUrl(url: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SponsoredMessage: TypeConstructorDescription { - case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer?, chatInvite: Api.ChatInvite?, chatInviteHash: String?, channelPost: Int32?, startParam: String?, message: String, entities: [Api.MessageEntity]?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let message, let entities): - if boxed { - buffer.appendInt32(981691896) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeBytes(randomId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {fromId!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {chatInvite!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(chatInviteHash!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let message, let entities): - return ("sponsoredMessage", [("flags", String(describing: flags)), ("randomId", String(describing: randomId)), ("fromId", String(describing: fromId)), ("chatInvite", String(describing: chatInvite)), ("chatInviteHash", String(describing: chatInviteHash)), ("channelPost", String(describing: channelPost)), ("startParam", String(describing: startParam)), ("message", String(describing: message)), ("entities", String(describing: entities))]) - } - } - - public static func parse_sponsoredMessage(_ reader: BufferReader) -> SponsoredMessage? { + public static func parse_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? { var _1: Int32? _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Api.Peer? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } } - var _4: Api.ChatInvite? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.ChatInvite - } } - var _5: String? - if Int(_1!) & Int(1 << 4) != 0 {_5 = parseString(reader) } - var _6: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() } - var _7: String? - if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) } - var _8: String? - _8 = parseString(reader) - var _9: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil - let _c8 = _8 != nil - let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, fromId: _3, chatInvite: _4, chatInviteHash: _5, channelPost: _6, startParam: _7, message: _8!, entities: _9) - } - else { - return nil - } - } - - } -} -public extension Api { - enum StatsAbsValueAndPrev: TypeConstructorDescription { - case statsAbsValueAndPrev(current: Double, previous: Double) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsAbsValueAndPrev(let current, let previous): - if boxed { - buffer.appendInt32(-884757282) - } - serializeDouble(current, buffer: buffer, boxed: false) - serializeDouble(previous, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsAbsValueAndPrev(let current, let previous): - return ("statsAbsValueAndPrev", [("current", String(describing: current)), ("previous", String(describing: previous))]) - } - } - - public static func parse_statsAbsValueAndPrev(_ reader: BufferReader) -> StatsAbsValueAndPrev? { - var _1: Double? - _1 = reader.readDouble() - var _2: Double? - _2 = reader.readDouble() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StatsAbsValueAndPrev.statsAbsValueAndPrev(current: _1!, previous: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum StatsDateRangeDays: TypeConstructorDescription { - case statsDateRangeDays(minDate: Int32, maxDate: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsDateRangeDays(let minDate, let maxDate): - if boxed { - buffer.appendInt32(-1237848657) - } - serializeInt32(minDate, buffer: buffer, boxed: false) - serializeInt32(maxDate, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsDateRangeDays(let minDate, let maxDate): - return ("statsDateRangeDays", [("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]) - } - } - - public static func parse_statsDateRangeDays(_ reader: BufferReader) -> StatsDateRangeDays? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StatsDateRangeDays.statsDateRangeDays(minDate: _1!, maxDate: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum StatsGraph: TypeConstructorDescription { - case statsGraph(flags: Int32, json: Api.DataJSON, zoomToken: String?) - case statsGraphAsync(token: String) - case statsGraphError(error: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsGraph(let flags, let json, let zoomToken): - if boxed { - buffer.appendInt32(-1901828938) - } - serializeInt32(flags, buffer: buffer, boxed: false) - json.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeString(zoomToken!, buffer: buffer, boxed: false)} - break - case .statsGraphAsync(let token): - if boxed { - buffer.appendInt32(1244130093) - } - serializeString(token, buffer: buffer, boxed: false) - break - case .statsGraphError(let error): - if boxed { - buffer.appendInt32(-1092839390) - } - serializeString(error, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsGraph(let flags, let json, let zoomToken): - return ("statsGraph", [("flags", String(describing: flags)), ("json", String(describing: json)), ("zoomToken", String(describing: zoomToken))]) - case .statsGraphAsync(let token): - return ("statsGraphAsync", [("token", String(describing: token))]) - case .statsGraphError(let error): - return ("statsGraphError", [("error", String(describing: error))]) - } - } - - public static func parse_statsGraph(_ reader: BufferReader) -> StatsGraph? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.DataJSON? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - var _3: String? - if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.StatsGraph.statsGraph(flags: _1!, json: _2!, zoomToken: _3) - } - else { - return nil - } - } - public static func parse_statsGraphAsync(_ reader: BufferReader) -> StatsGraph? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.StatsGraph.statsGraphAsync(token: _1!) - } - else { - return nil - } - } - public static func parse_statsGraphError(_ reader: BufferReader) -> StatsGraph? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.StatsGraph.statsGraphError(error: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum StatsGroupTopAdmin: TypeConstructorDescription { - case statsGroupTopAdmin(userId: Int64, deleted: Int32, kicked: Int32, banned: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsGroupTopAdmin(let userId, let deleted, let kicked, let banned): - if boxed { - buffer.appendInt32(-682079097) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(deleted, buffer: buffer, boxed: false) - serializeInt32(kicked, buffer: buffer, boxed: false) - serializeInt32(banned, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsGroupTopAdmin(let userId, let deleted, let kicked, let banned): - return ("statsGroupTopAdmin", [("userId", String(describing: userId)), ("deleted", String(describing: deleted)), ("kicked", String(describing: kicked)), ("banned", String(describing: banned))]) - } - } - - public static func parse_statsGroupTopAdmin(_ reader: BufferReader) -> StatsGroupTopAdmin? { - var _1: Int64? - _1 = reader.readInt64() var _2: Int32? _2 = reader.readInt32() var _3: Int32? @@ -673,7 +85,7 @@ public extension Api { let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.StatsGroupTopAdmin.statsGroupTopAdmin(userId: _1!, deleted: _2!, kicked: _3!, banned: _4!) + return Api.SearchResultsCalendarPeriod.searchResultsCalendarPeriod(date: _1!, minMsgId: _2!, maxMsgId: _3!, count: _4!) } else { return nil @@ -683,72 +95,32 @@ public extension Api { } } public extension Api { - enum StatsGroupTopInviter: TypeConstructorDescription { - case statsGroupTopInviter(userId: Int64, invitations: Int32) + enum SearchResultsPosition: TypeConstructorDescription { + case searchResultPosition(msgId: Int32, date: Int32, offset: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .statsGroupTopInviter(let userId, let invitations): + case .searchResultPosition(let msgId, let date, let offset): if boxed { - buffer.appendInt32(1398765469) + buffer.appendInt32(2137295719) } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(invitations, buffer: buffer, boxed: false) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(offset, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .statsGroupTopInviter(let userId, let invitations): - return ("statsGroupTopInviter", [("userId", String(describing: userId)), ("invitations", String(describing: invitations))]) + case .searchResultPosition(let msgId, let date, let offset): + return ("searchResultPosition", [("msgId", String(describing: msgId)), ("date", String(describing: date)), ("offset", String(describing: offset))]) } } - public static func parse_statsGroupTopInviter(_ reader: BufferReader) -> StatsGroupTopInviter? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StatsGroupTopInviter.statsGroupTopInviter(userId: _1!, invitations: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum StatsGroupTopPoster: TypeConstructorDescription { - case statsGroupTopPoster(userId: Int64, messages: Int32, avgChars: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsGroupTopPoster(let userId, let messages, let avgChars): - if boxed { - buffer.appendInt32(-1660637285) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(messages, buffer: buffer, boxed: false) - serializeInt32(avgChars, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsGroupTopPoster(let userId, let messages, let avgChars): - return ("statsGroupTopPoster", [("userId", String(describing: userId)), ("messages", String(describing: messages)), ("avgChars", String(describing: avgChars))]) - } - } - - public static func parse_statsGroupTopPoster(_ reader: BufferReader) -> StatsGroupTopPoster? { - var _1: Int64? - _1 = reader.readInt64() + public static func parse_searchResultPosition(_ reader: BufferReader) -> SearchResultsPosition? { + var _1: Int32? + _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() var _3: Int32? @@ -757,7 +129,7 @@ public extension Api { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.StatsGroupTopPoster.statsGroupTopPoster(userId: _1!, messages: _2!, avgChars: _3!) + return Api.SearchResultsPosition.searchResultPosition(msgId: _1!, date: _2!, offset: _3!) } else { return nil @@ -767,37 +139,41 @@ public extension Api { } } public extension Api { - enum StatsPercentValue: TypeConstructorDescription { - case statsPercentValue(part: Double, total: Double) + enum SecureCredentialsEncrypted: TypeConstructorDescription { + case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .statsPercentValue(let part, let total): + case .secureCredentialsEncrypted(let data, let hash, let secret): if boxed { - buffer.appendInt32(-875679776) + buffer.appendInt32(871426631) } - serializeDouble(part, buffer: buffer, boxed: false) - serializeDouble(total, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + serializeBytes(hash, buffer: buffer, boxed: false) + serializeBytes(secret, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .statsPercentValue(let part, let total): - return ("statsPercentValue", [("part", String(describing: part)), ("total", String(describing: total))]) + case .secureCredentialsEncrypted(let data, let hash, let secret): + return ("secureCredentialsEncrypted", [("data", String(describing: data)), ("hash", String(describing: hash)), ("secret", String(describing: secret))]) } } - public static func parse_statsPercentValue(_ reader: BufferReader) -> StatsPercentValue? { - var _1: Double? - _1 = reader.readDouble() - var _2: Double? - _2 = reader.readDouble() + public static func parse_secureCredentialsEncrypted(_ reader: BufferReader) -> SecureCredentialsEncrypted? { + var _1: Buffer? + _1 = parseBytes(reader) + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Buffer? + _3 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StatsPercentValue.statsPercentValue(part: _1!, total: _2!) + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!) } else { return nil @@ -807,33 +183,237 @@ public extension Api { } } public extension Api { - enum StatsURL: TypeConstructorDescription { - case statsURL(url: String) + enum SecureData: TypeConstructorDescription { + case secureData(data: Buffer, dataHash: Buffer, secret: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .statsURL(let url): + case .secureData(let data, let dataHash, let secret): if boxed { - buffer.appendInt32(1202287072) + buffer.appendInt32(-1964327229) } - serializeString(url, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + serializeBytes(dataHash, buffer: buffer, boxed: false) + serializeBytes(secret, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .statsURL(let url): - return ("statsURL", [("url", String(describing: url))]) + case .secureData(let data, let dataHash, let secret): + return ("secureData", [("data", String(describing: data)), ("dataHash", String(describing: dataHash)), ("secret", String(describing: secret))]) } } - public static func parse_statsURL(_ reader: BufferReader) -> StatsURL? { + public static func parse_secureData(_ reader: BufferReader) -> SecureData? { + var _1: Buffer? + _1 = parseBytes(reader) + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Buffer? + _3 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureData.secureData(data: _1!, dataHash: _2!, secret: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SecureFile: TypeConstructorDescription { + case secureFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer) + case secureFileEmpty + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret): + if boxed { + buffer.appendInt32(2097791614) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt64(size, buffer: buffer, boxed: false) + serializeInt32(dcId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeBytes(secret, buffer: buffer, boxed: false) + break + case .secureFileEmpty: + if boxed { + buffer.appendInt32(1679398724) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret): + return ("secureFile", [("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("size", String(describing: size)), ("dcId", String(describing: dcId)), ("date", String(describing: date)), ("fileHash", String(describing: fileHash)), ("secret", String(describing: secret))]) + case .secureFileEmpty: + return ("secureFileEmpty", []) + } + } + + public static func parse_secureFile(_ reader: BufferReader) -> SecureFile? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Buffer? + _6 = parseBytes(reader) + var _7: Buffer? + _7 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.SecureFile.secureFile(id: _1!, accessHash: _2!, size: _3!, dcId: _4!, date: _5!, fileHash: _6!, secret: _7!) + } + else { + return nil + } + } + public static func parse_secureFileEmpty(_ reader: BufferReader) -> SecureFile? { + return Api.SecureFile.secureFileEmpty + } + + } +} +public extension Api { + enum SecurePasswordKdfAlgo: TypeConstructorDescription { + case securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: Buffer) + case securePasswordKdfAlgoSHA512(salt: Buffer) + case securePasswordKdfAlgoUnknown + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(let salt): + if boxed { + buffer.appendInt32(-1141711456) + } + serializeBytes(salt, buffer: buffer, boxed: false) + break + case .securePasswordKdfAlgoSHA512(let salt): + if boxed { + buffer.appendInt32(-2042159726) + } + serializeBytes(salt, buffer: buffer, boxed: false) + break + case .securePasswordKdfAlgoUnknown: + if boxed { + buffer.appendInt32(4883767) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(let salt): + return ("securePasswordKdfAlgoPBKDF2HMACSHA512iter100000", [("salt", String(describing: salt))]) + case .securePasswordKdfAlgoSHA512(let salt): + return ("securePasswordKdfAlgoSHA512", [("salt", String(describing: salt))]) + case .securePasswordKdfAlgoUnknown: + return ("securePasswordKdfAlgoUnknown", []) + } + } + + public static func parse_securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: _1!) + } + else { + return nil + } + } + public static func parse_securePasswordKdfAlgoSHA512(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoSHA512(salt: _1!) + } + else { + return nil + } + } + public static func parse_securePasswordKdfAlgoUnknown(_ reader: BufferReader) -> SecurePasswordKdfAlgo? { + return Api.SecurePasswordKdfAlgo.securePasswordKdfAlgoUnknown + } + + } +} +public extension Api { + enum SecurePlainData: TypeConstructorDescription { + case securePlainEmail(email: String) + case securePlainPhone(phone: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .securePlainEmail(let email): + if boxed { + buffer.appendInt32(569137759) + } + serializeString(email, buffer: buffer, boxed: false) + break + case .securePlainPhone(let phone): + if boxed { + buffer.appendInt32(2103482845) + } + serializeString(phone, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .securePlainEmail(let email): + return ("securePlainEmail", [("email", String(describing: email))]) + case .securePlainPhone(let phone): + return ("securePlainPhone", [("phone", String(describing: phone))]) + } + } + + public static func parse_securePlainEmail(_ reader: BufferReader) -> SecurePlainData? { var _1: String? _1 = parseString(reader) let _c1 = _1 != nil if _c1 { - return Api.StatsURL.statsURL(url: _1!) + return Api.SecurePlainData.securePlainEmail(email: _1!) + } + else { + return nil + } + } + public static func parse_securePlainPhone(_ reader: BufferReader) -> SecurePlainData? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.SecurePlainData.securePlainPhone(phone: _1!) } else { return nil @@ -843,20 +423,27 @@ public extension Api { } } public extension Api { - enum StickerPack: TypeConstructorDescription { - case stickerPack(emoticon: String, documents: [Int64]) + enum SecureRequiredType: TypeConstructorDescription { + case secureRequiredType(flags: Int32, type: Api.SecureValueType) + case secureRequiredTypeOneOf(types: [Api.SecureRequiredType]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .stickerPack(let emoticon, let documents): + case .secureRequiredType(let flags, let type): if boxed { - buffer.appendInt32(313694676) + buffer.appendInt32(-2103600678) + } + serializeInt32(flags, buffer: buffer, boxed: false) + type.serialize(buffer, true) + break + case .secureRequiredTypeOneOf(let types): + if boxed { + buffer.appendInt32(41187252) } - serializeString(emoticon, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(documents.count)) - for item in documents { - serializeInt64(item, buffer: buffer, boxed: false) + buffer.appendInt32(Int32(types.count)) + for item in types { + item.serialize(buffer, true) } break } @@ -864,22 +451,37 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .stickerPack(let emoticon, let documents): - return ("stickerPack", [("emoticon", String(describing: emoticon)), ("documents", String(describing: documents))]) + case .secureRequiredType(let flags, let type): + return ("secureRequiredType", [("flags", String(describing: flags)), ("type", String(describing: type))]) + case .secureRequiredTypeOneOf(let types): + return ("secureRequiredTypeOneOf", [("types", String(describing: types))]) } } - public static func parse_stickerPack(_ reader: BufferReader) -> StickerPack? { - var _1: String? - _1 = parseString(reader) - var _2: [Int64]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + public static func parse_secureRequiredType(_ reader: BufferReader) -> SecureRequiredType? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.SecureValueType? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.SecureValueType } let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.StickerPack.stickerPack(emoticon: _1!, documents: _2!) + return Api.SecureRequiredType.secureRequiredType(flags: _1!, type: _2!) + } + else { + return nil + } + } + public static func parse_secureRequiredTypeOneOf(_ reader: BufferReader) -> SecureRequiredType? { + var _1: [Api.SecureRequiredType]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureRequiredType.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.SecureRequiredType.secureRequiredTypeOneOf(types: _1!) } else { return nil @@ -888,3 +490,661 @@ public extension Api { } } +public extension Api { + enum SecureSecretSettings: TypeConstructorDescription { + case secureSecretSettings(secureAlgo: Api.SecurePasswordKdfAlgo, secureSecret: Buffer, secureSecretId: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureSecretSettings(let secureAlgo, let secureSecret, let secureSecretId): + if boxed { + buffer.appendInt32(354925740) + } + secureAlgo.serialize(buffer, true) + serializeBytes(secureSecret, buffer: buffer, boxed: false) + serializeInt64(secureSecretId, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureSecretSettings(let secureAlgo, let secureSecret, let secureSecretId): + return ("secureSecretSettings", [("secureAlgo", String(describing: secureAlgo)), ("secureSecret", String(describing: secureSecret)), ("secureSecretId", String(describing: secureSecretId))]) + } + } + + public static func parse_secureSecretSettings(_ reader: BufferReader) -> SecureSecretSettings? { + var _1: Api.SecurePasswordKdfAlgo? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecurePasswordKdfAlgo + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Int64? + _3 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureSecretSettings.secureSecretSettings(secureAlgo: _1!, secureSecret: _2!, secureSecretId: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SecureValue: TypeConstructorDescription { + case secureValue(flags: Int32, type: Api.SecureValueType, data: Api.SecureData?, frontSide: Api.SecureFile?, reverseSide: Api.SecureFile?, selfie: Api.SecureFile?, translation: [Api.SecureFile]?, files: [Api.SecureFile]?, plainData: Api.SecurePlainData?, hash: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureValue(let flags, let type, let data, let frontSide, let reverseSide, let selfie, let translation, let files, let plainData, let hash): + if boxed { + buffer.appendInt32(411017418) + } + serializeInt32(flags, buffer: buffer, boxed: false) + type.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {data!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {frontSide!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {reverseSide!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {selfie!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(translation!.count)) + for item in translation! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(files!.count)) + for item in files! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 5) != 0 {plainData!.serialize(buffer, true)} + serializeBytes(hash, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureValue(let flags, let type, let data, let frontSide, let reverseSide, let selfie, let translation, let files, let plainData, let hash): + return ("secureValue", [("flags", String(describing: flags)), ("type", String(describing: type)), ("data", String(describing: data)), ("frontSide", String(describing: frontSide)), ("reverseSide", String(describing: reverseSide)), ("selfie", String(describing: selfie)), ("translation", String(describing: translation)), ("files", String(describing: files)), ("plainData", String(describing: plainData)), ("hash", String(describing: hash))]) + } + } + + public static func parse_secureValue(_ reader: BufferReader) -> SecureValue? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.SecureValueType? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _3: Api.SecureData? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.SecureData + } } + var _4: Api.SecureFile? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.SecureFile + } } + var _5: Api.SecureFile? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.SecureFile + } } + var _6: Api.SecureFile? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.SecureFile + } } + var _7: [Api.SecureFile]? + if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureFile.self) + } } + var _8: [Api.SecureFile]? + if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { + _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureFile.self) + } } + var _9: Api.SecurePlainData? + if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.SecurePlainData + } } + var _10: Buffer? + _10 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 5) == 0) || _9 != nil + let _c10 = _10 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { + return Api.SecureValue.secureValue(flags: _1!, type: _2!, data: _3, frontSide: _4, reverseSide: _5, selfie: _6, translation: _7, files: _8, plainData: _9, hash: _10!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SecureValueError: TypeConstructorDescription { + case secureValueError(type: Api.SecureValueType, hash: Buffer, text: String) + case secureValueErrorData(type: Api.SecureValueType, dataHash: Buffer, field: String, text: String) + case secureValueErrorFile(type: Api.SecureValueType, fileHash: Buffer, text: String) + case secureValueErrorFiles(type: Api.SecureValueType, fileHash: [Buffer], text: String) + case secureValueErrorFrontSide(type: Api.SecureValueType, fileHash: Buffer, text: String) + case secureValueErrorReverseSide(type: Api.SecureValueType, fileHash: Buffer, text: String) + case secureValueErrorSelfie(type: Api.SecureValueType, fileHash: Buffer, text: String) + case secureValueErrorTranslationFile(type: Api.SecureValueType, fileHash: Buffer, text: String) + case secureValueErrorTranslationFiles(type: Api.SecureValueType, fileHash: [Buffer], text: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureValueError(let type, let hash, let text): + if boxed { + buffer.appendInt32(-2036501105) + } + type.serialize(buffer, true) + serializeBytes(hash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorData(let type, let dataHash, let field, let text): + if boxed { + buffer.appendInt32(-391902247) + } + type.serialize(buffer, true) + serializeBytes(dataHash, buffer: buffer, boxed: false) + serializeString(field, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorFile(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(2054162547) + } + type.serialize(buffer, true) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorFiles(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(1717706985) + } + type.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(fileHash.count)) + for item in fileHash { + serializeBytes(item, buffer: buffer, boxed: false) + } + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorFrontSide(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(12467706) + } + type.serialize(buffer, true) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorReverseSide(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(-2037765467) + } + type.serialize(buffer, true) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorSelfie(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(-449327402) + } + type.serialize(buffer, true) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorTranslationFile(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(-1592506512) + } + type.serialize(buffer, true) + serializeBytes(fileHash, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .secureValueErrorTranslationFiles(let type, let fileHash, let text): + if boxed { + buffer.appendInt32(878931416) + } + type.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(fileHash.count)) + for item in fileHash { + serializeBytes(item, buffer: buffer, boxed: false) + } + serializeString(text, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureValueError(let type, let hash, let text): + return ("secureValueError", [("type", String(describing: type)), ("hash", String(describing: hash)), ("text", String(describing: text))]) + case .secureValueErrorData(let type, let dataHash, let field, let text): + return ("secureValueErrorData", [("type", String(describing: type)), ("dataHash", String(describing: dataHash)), ("field", String(describing: field)), ("text", String(describing: text))]) + case .secureValueErrorFile(let type, let fileHash, let text): + return ("secureValueErrorFile", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorFiles(let type, let fileHash, let text): + return ("secureValueErrorFiles", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorFrontSide(let type, let fileHash, let text): + return ("secureValueErrorFrontSide", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorReverseSide(let type, let fileHash, let text): + return ("secureValueErrorReverseSide", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorSelfie(let type, let fileHash, let text): + return ("secureValueErrorSelfie", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorTranslationFile(let type, let fileHash, let text): + return ("secureValueErrorTranslationFile", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + case .secureValueErrorTranslationFiles(let type, let fileHash, let text): + return ("secureValueErrorTranslationFiles", [("type", String(describing: type)), ("fileHash", String(describing: fileHash)), ("text", String(describing: text))]) + } + } + + public static func parse_secureValueError(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueError(type: _1!, hash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorData(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.SecureValueError.secureValueErrorData(type: _1!, dataHash: _2!, field: _3!, text: _4!) + } + else { + return nil + } + } + public static func parse_secureValueErrorFile(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorFile(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorFiles(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: [Buffer]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) + } + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorFiles(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorFrontSide(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorFrontSide(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorReverseSide(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorReverseSide(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorSelfie(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorSelfie(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorTranslationFile(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorTranslationFile(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + public static func parse_secureValueErrorTranslationFiles(_ reader: BufferReader) -> SecureValueError? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: [Buffer]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) + } + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.SecureValueError.secureValueErrorTranslationFiles(type: _1!, fileHash: _2!, text: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SecureValueHash: TypeConstructorDescription { + case secureValueHash(type: Api.SecureValueType, hash: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureValueHash(let type, let hash): + if boxed { + buffer.appendInt32(-316748368) + } + type.serialize(buffer, true) + serializeBytes(hash, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureValueHash(let type, let hash): + return ("secureValueHash", [("type", String(describing: type)), ("hash", String(describing: hash))]) + } + } + + public static func parse_secureValueHash(_ reader: BufferReader) -> SecureValueHash? { + var _1: Api.SecureValueType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.SecureValueType + } + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.SecureValueHash.secureValueHash(type: _1!, hash: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SecureValueType: TypeConstructorDescription { + case secureValueTypeAddress + case secureValueTypeBankStatement + case secureValueTypeDriverLicense + case secureValueTypeEmail + case secureValueTypeIdentityCard + case secureValueTypeInternalPassport + case secureValueTypePassport + case secureValueTypePassportRegistration + case secureValueTypePersonalDetails + case secureValueTypePhone + case secureValueTypeRentalAgreement + case secureValueTypeTemporaryRegistration + case secureValueTypeUtilityBill + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .secureValueTypeAddress: + if boxed { + buffer.appendInt32(-874308058) + } + + break + case .secureValueTypeBankStatement: + if boxed { + buffer.appendInt32(-1995211763) + } + + break + case .secureValueTypeDriverLicense: + if boxed { + buffer.appendInt32(115615172) + } + + break + case .secureValueTypeEmail: + if boxed { + buffer.appendInt32(-1908627474) + } + + break + case .secureValueTypeIdentityCard: + if boxed { + buffer.appendInt32(-1596951477) + } + + break + case .secureValueTypeInternalPassport: + if boxed { + buffer.appendInt32(-1717268701) + } + + break + case .secureValueTypePassport: + if boxed { + buffer.appendInt32(1034709504) + } + + break + case .secureValueTypePassportRegistration: + if boxed { + buffer.appendInt32(-1713143702) + } + + break + case .secureValueTypePersonalDetails: + if boxed { + buffer.appendInt32(-1658158621) + } + + break + case .secureValueTypePhone: + if boxed { + buffer.appendInt32(-1289704741) + } + + break + case .secureValueTypeRentalAgreement: + if boxed { + buffer.appendInt32(-1954007928) + } + + break + case .secureValueTypeTemporaryRegistration: + if boxed { + buffer.appendInt32(-368907213) + } + + break + case .secureValueTypeUtilityBill: + if boxed { + buffer.appendInt32(-63531698) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .secureValueTypeAddress: + return ("secureValueTypeAddress", []) + case .secureValueTypeBankStatement: + return ("secureValueTypeBankStatement", []) + case .secureValueTypeDriverLicense: + return ("secureValueTypeDriverLicense", []) + case .secureValueTypeEmail: + return ("secureValueTypeEmail", []) + case .secureValueTypeIdentityCard: + return ("secureValueTypeIdentityCard", []) + case .secureValueTypeInternalPassport: + return ("secureValueTypeInternalPassport", []) + case .secureValueTypePassport: + return ("secureValueTypePassport", []) + case .secureValueTypePassportRegistration: + return ("secureValueTypePassportRegistration", []) + case .secureValueTypePersonalDetails: + return ("secureValueTypePersonalDetails", []) + case .secureValueTypePhone: + return ("secureValueTypePhone", []) + case .secureValueTypeRentalAgreement: + return ("secureValueTypeRentalAgreement", []) + case .secureValueTypeTemporaryRegistration: + return ("secureValueTypeTemporaryRegistration", []) + case .secureValueTypeUtilityBill: + return ("secureValueTypeUtilityBill", []) + } + } + + public static func parse_secureValueTypeAddress(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeAddress + } + public static func parse_secureValueTypeBankStatement(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeBankStatement + } + public static func parse_secureValueTypeDriverLicense(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeDriverLicense + } + public static func parse_secureValueTypeEmail(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeEmail + } + public static func parse_secureValueTypeIdentityCard(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeIdentityCard + } + public static func parse_secureValueTypeInternalPassport(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeInternalPassport + } + public static func parse_secureValueTypePassport(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypePassport + } + public static func parse_secureValueTypePassportRegistration(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypePassportRegistration + } + public static func parse_secureValueTypePersonalDetails(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypePersonalDetails + } + public static func parse_secureValueTypePhone(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypePhone + } + public static func parse_secureValueTypeRentalAgreement(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeRentalAgreement + } + public static func parse_secureValueTypeTemporaryRegistration(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeTemporaryRegistration + } + public static func parse_secureValueTypeUtilityBill(_ reader: BufferReader) -> SecureValueType? { + return Api.SecureValueType.secureValueTypeUtilityBill + } + + } +} diff --git a/submodules/TelegramApi/Sources/Api19.swift b/submodules/TelegramApi/Sources/Api19.swift index 7f1724a2b6..8e3e101b48 100644 --- a/submodules/TelegramApi/Sources/Api19.swift +++ b/submodules/TelegramApi/Sources/Api19.swift @@ -1,229 +1,351 @@ public extension Api { - enum StickerSet: TypeConstructorDescription { - case stickerSet(flags: Int32, installedDate: Int32?, id: Int64, accessHash: Int64, title: String, shortName: String, thumbs: [Api.PhotoSize]?, thumbDcId: Int32?, thumbVersion: Int32?, count: Int32, hash: Int32) + enum SendMessageAction: TypeConstructorDescription { + case sendMessageCancelAction + case sendMessageChooseContactAction + case sendMessageChooseStickerAction + case sendMessageEmojiInteraction(emoticon: String, msgId: Int32, interaction: Api.DataJSON) + case sendMessageEmojiInteractionSeen(emoticon: String) + case sendMessageGamePlayAction + case sendMessageGeoLocationAction + case sendMessageHistoryImportAction(progress: Int32) + case sendMessageRecordAudioAction + case sendMessageRecordRoundAction + case sendMessageRecordVideoAction + case sendMessageTypingAction + case sendMessageUploadAudioAction(progress: Int32) + case sendMessageUploadDocumentAction(progress: Int32) + case sendMessageUploadPhotoAction(progress: Int32) + case sendMessageUploadRoundAction(progress: Int32) + case sendMessageUploadVideoAction(progress: Int32) + case speakingInGroupCallAction public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .stickerSet(let flags, let installedDate, let id, let accessHash, let title, let shortName, let thumbs, let thumbDcId, let thumbVersion, let count, let hash): + case .sendMessageCancelAction: if boxed { - buffer.appendInt32(-673242758) + buffer.appendInt32(-44119819) } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(installedDate!, buffer: buffer, boxed: false)} - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(shortName, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(thumbs!.count)) - for item in thumbs! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(thumbDcId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(thumbVersion!, buffer: buffer, boxed: false)} - serializeInt32(count, buffer: buffer, boxed: false) - serializeInt32(hash, buffer: buffer, boxed: false) + + break + case .sendMessageChooseContactAction: + if boxed { + buffer.appendInt32(1653390447) + } + + break + case .sendMessageChooseStickerAction: + if boxed { + buffer.appendInt32(-1336228175) + } + + break + case .sendMessageEmojiInteraction(let emoticon, let msgId, let interaction): + if boxed { + buffer.appendInt32(630664139) + } + serializeString(emoticon, buffer: buffer, boxed: false) + serializeInt32(msgId, buffer: buffer, boxed: false) + interaction.serialize(buffer, true) + break + case .sendMessageEmojiInteractionSeen(let emoticon): + if boxed { + buffer.appendInt32(-1234857938) + } + serializeString(emoticon, buffer: buffer, boxed: false) + break + case .sendMessageGamePlayAction: + if boxed { + buffer.appendInt32(-580219064) + } + + break + case .sendMessageGeoLocationAction: + if boxed { + buffer.appendInt32(393186209) + } + + break + case .sendMessageHistoryImportAction(let progress): + if boxed { + buffer.appendInt32(-606432698) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .sendMessageRecordAudioAction: + if boxed { + buffer.appendInt32(-718310409) + } + + break + case .sendMessageRecordRoundAction: + if boxed { + buffer.appendInt32(-1997373508) + } + + break + case .sendMessageRecordVideoAction: + if boxed { + buffer.appendInt32(-1584933265) + } + + break + case .sendMessageTypingAction: + if boxed { + buffer.appendInt32(381645902) + } + + break + case .sendMessageUploadAudioAction(let progress): + if boxed { + buffer.appendInt32(-212740181) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .sendMessageUploadDocumentAction(let progress): + if boxed { + buffer.appendInt32(-1441998364) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .sendMessageUploadPhotoAction(let progress): + if boxed { + buffer.appendInt32(-774682074) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .sendMessageUploadRoundAction(let progress): + if boxed { + buffer.appendInt32(608050278) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .sendMessageUploadVideoAction(let progress): + if boxed { + buffer.appendInt32(-378127636) + } + serializeInt32(progress, buffer: buffer, boxed: false) + break + case .speakingInGroupCallAction: + if boxed { + buffer.appendInt32(-651419003) + } + break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .stickerSet(let flags, let installedDate, let id, let accessHash, let title, let shortName, let thumbs, let thumbDcId, let thumbVersion, let count, let hash): - return ("stickerSet", [("flags", String(describing: flags)), ("installedDate", String(describing: installedDate)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("title", String(describing: title)), ("shortName", String(describing: shortName)), ("thumbs", String(describing: thumbs)), ("thumbDcId", String(describing: thumbDcId)), ("thumbVersion", String(describing: thumbVersion)), ("count", String(describing: count)), ("hash", String(describing: hash))]) + case .sendMessageCancelAction: + return ("sendMessageCancelAction", []) + case .sendMessageChooseContactAction: + return ("sendMessageChooseContactAction", []) + case .sendMessageChooseStickerAction: + return ("sendMessageChooseStickerAction", []) + case .sendMessageEmojiInteraction(let emoticon, let msgId, let interaction): + return ("sendMessageEmojiInteraction", [("emoticon", String(describing: emoticon)), ("msgId", String(describing: msgId)), ("interaction", String(describing: interaction))]) + case .sendMessageEmojiInteractionSeen(let emoticon): + return ("sendMessageEmojiInteractionSeen", [("emoticon", String(describing: emoticon))]) + case .sendMessageGamePlayAction: + return ("sendMessageGamePlayAction", []) + case .sendMessageGeoLocationAction: + return ("sendMessageGeoLocationAction", []) + case .sendMessageHistoryImportAction(let progress): + return ("sendMessageHistoryImportAction", [("progress", String(describing: progress))]) + case .sendMessageRecordAudioAction: + return ("sendMessageRecordAudioAction", []) + case .sendMessageRecordRoundAction: + return ("sendMessageRecordRoundAction", []) + case .sendMessageRecordVideoAction: + return ("sendMessageRecordVideoAction", []) + case .sendMessageTypingAction: + return ("sendMessageTypingAction", []) + case .sendMessageUploadAudioAction(let progress): + return ("sendMessageUploadAudioAction", [("progress", String(describing: progress))]) + case .sendMessageUploadDocumentAction(let progress): + return ("sendMessageUploadDocumentAction", [("progress", String(describing: progress))]) + case .sendMessageUploadPhotoAction(let progress): + return ("sendMessageUploadPhotoAction", [("progress", String(describing: progress))]) + case .sendMessageUploadRoundAction(let progress): + return ("sendMessageUploadRoundAction", [("progress", String(describing: progress))]) + case .sendMessageUploadVideoAction(let progress): + return ("sendMessageUploadVideoAction", [("progress", String(describing: progress))]) + case .speakingInGroupCallAction: + return ("speakingInGroupCallAction", []) } } - public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { - var _1: Int32? - _1 = reader.readInt32() + public static func parse_sendMessageCancelAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageCancelAction + } + public static func parse_sendMessageChooseContactAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageChooseContactAction + } + public static func parse_sendMessageChooseStickerAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageChooseStickerAction + } + public static func parse_sendMessageEmojiInteraction(_ reader: BufferReader) -> SendMessageAction? { + var _1: String? + _1 = parseString(reader) var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: Int64? - _3 = reader.readInt64() - var _4: Int64? - _4 = reader.readInt64() - var _5: String? - _5 = parseString(reader) - var _6: String? - _6 = parseString(reader) - var _7: [Api.PhotoSize]? - if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self) - } } - var _8: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } - var _9: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_9 = reader.readInt32() } - var _10: Int32? - _10 = reader.readInt32() - var _11: Int32? - _11 = reader.readInt32() + _2 = reader.readInt32() + var _3: Api.DataJSON? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.DataJSON + } let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 4) == 0) || _9 != nil - let _c10 = _10 != nil - let _c11 = _11 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 { - return Api.StickerSet.stickerSet(flags: _1!, installedDate: _2, id: _3!, accessHash: _4!, title: _5!, shortName: _6!, thumbs: _7, thumbDcId: _8, thumbVersion: _9, count: _10!, hash: _11!) + if _c1 && _c2 && _c3 { + return Api.SendMessageAction.sendMessageEmojiInteraction(emoticon: _1!, msgId: _2!, interaction: _3!) } else { return nil } } + public static func parse_sendMessageEmojiInteractionSeen(_ reader: BufferReader) -> SendMessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageEmojiInteractionSeen(emoticon: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageGamePlayAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageGamePlayAction + } + public static func parse_sendMessageGeoLocationAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageGeoLocationAction + } + public static func parse_sendMessageHistoryImportAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageHistoryImportAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageRecordAudioAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageRecordAudioAction + } + public static func parse_sendMessageRecordRoundAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageRecordRoundAction + } + public static func parse_sendMessageRecordVideoAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageRecordVideoAction + } + public static func parse_sendMessageTypingAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.sendMessageTypingAction + } + public static func parse_sendMessageUploadAudioAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageUploadAudioAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageUploadDocumentAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageUploadDocumentAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageUploadPhotoAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageUploadPhotoAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageUploadRoundAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageUploadRoundAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_sendMessageUploadVideoAction(_ reader: BufferReader) -> SendMessageAction? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.SendMessageAction.sendMessageUploadVideoAction(progress: _1!) + } + else { + return nil + } + } + public static func parse_speakingInGroupCallAction(_ reader: BufferReader) -> SendMessageAction? { + return Api.SendMessageAction.speakingInGroupCallAction + } } } public extension Api { - enum StickerSetCovered: TypeConstructorDescription { - case stickerSetCovered(set: Api.StickerSet, cover: Api.Document) - case stickerSetMultiCovered(set: Api.StickerSet, covers: [Api.Document]) + enum ShippingOption: TypeConstructorDescription { + case shippingOption(id: String, title: String, prices: [Api.LabeledPrice]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .stickerSetCovered(let set, let cover): + case .shippingOption(let id, let title, let prices): if boxed { - buffer.appendInt32(1678812626) + buffer.appendInt32(-1239335713) } - set.serialize(buffer, true) - cover.serialize(buffer, true) - break - case .stickerSetMultiCovered(let set, let covers): - if boxed { - buffer.appendInt32(872932635) - } - set.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(covers.count)) - for item in covers { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stickerSetCovered(let set, let cover): - return ("stickerSetCovered", [("set", String(describing: set)), ("cover", String(describing: cover))]) - case .stickerSetMultiCovered(let set, let covers): - return ("stickerSetMultiCovered", [("set", String(describing: set)), ("covers", String(describing: covers))]) - } - } - - public static func parse_stickerSetCovered(_ reader: BufferReader) -> StickerSetCovered? { - var _1: Api.StickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StickerSet - } - var _2: Api.Document? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Document - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StickerSetCovered.stickerSetCovered(set: _1!, cover: _2!) - } - else { - return nil - } - } - public static func parse_stickerSetMultiCovered(_ reader: BufferReader) -> StickerSetCovered? { - var _1: Api.StickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StickerSet - } - var _2: [Api.Document]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.StickerSetCovered.stickerSetMultiCovered(set: _1!, covers: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Theme: TypeConstructorDescription { - case theme(flags: Int32, id: Int64, accessHash: Int64, slug: String, title: String, document: Api.Document?, settings: [Api.ThemeSettings]?, emoticon: String?, installsCount: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .theme(let flags, let id, let accessHash, let slug, let title, let document, let settings, let emoticon, let installsCount): - if boxed { - buffer.appendInt32(-1609668650) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeString(slug, buffer: buffer, boxed: false) + serializeString(id, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(settings!.count)) - for item in settings! { + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prices.count)) + for item in prices { item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 6) != 0 {serializeString(emoticon!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(installsCount!, buffer: buffer, boxed: false)} + } break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .theme(let flags, let id, let accessHash, let slug, let title, let document, let settings, let emoticon, let installsCount): - return ("theme", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings)), ("emoticon", String(describing: emoticon)), ("installsCount", String(describing: installsCount))]) + case .shippingOption(let id, let title, let prices): + return ("shippingOption", [("id", String(describing: id)), ("title", String(describing: title)), ("prices", String(describing: prices))]) } } - public static func parse_theme(_ reader: BufferReader) -> Theme? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: Api.Document? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.Document - } } - var _7: [Api.ThemeSettings]? - if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ThemeSettings.self) - } } - var _8: String? - if Int(_1!) & Int(1 << 6) != 0 {_8 = parseString(reader) } - var _9: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_9 = reader.readInt32() } + public static func parse_shippingOption(_ reader: BufferReader) -> ShippingOption? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + var _3: [Api.LabeledPrice]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LabeledPrice.self) + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 6) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 4) == 0) || _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.Theme.theme(flags: _1!, id: _2!, accessHash: _3!, slug: _4!, title: _5!, document: _6, settings: _7, emoticon: _8, installsCount: _9) + if _c1 && _c2 && _c3 { + return Api.ShippingOption.shippingOption(id: _1!, title: _2!, prices: _3!) } else { return nil @@ -233,63 +355,111 @@ public extension Api { } } public extension Api { - enum ThemeSettings: TypeConstructorDescription { - case themeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.WallPaper?) + enum SimpleWebViewResult: TypeConstructorDescription { + case simpleWebViewResultUrl(url: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .themeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper): + case .simpleWebViewResultUrl(let url): if boxed { - buffer.appendInt32(-94849324) + buffer.appendInt32(-2010155333) + } + serializeString(url, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .simpleWebViewResultUrl(let url): + return ("simpleWebViewResultUrl", [("url", String(describing: url))]) + } + } + + public static func parse_simpleWebViewResultUrl(_ reader: BufferReader) -> SimpleWebViewResult? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.SimpleWebViewResult.simpleWebViewResultUrl(url: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum SponsoredMessage: TypeConstructorDescription { + case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer?, chatInvite: Api.ChatInvite?, chatInviteHash: String?, channelPost: Int32?, startParam: String?, message: String, entities: [Api.MessageEntity]?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let message, let entities): + if boxed { + buffer.appendInt32(981691896) } serializeInt32(flags, buffer: buffer, boxed: false) - baseTheme.serialize(buffer, true) - serializeInt32(accentColor, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messageColors!.count)) - for item in messageColors! { - serializeInt32(item, buffer: buffer, boxed: false) + serializeBytes(randomId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {fromId!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {chatInvite!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {serializeString(chatInviteHash!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) }} - if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .themeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper): - return ("themeSettings", [("flags", String(describing: flags)), ("baseTheme", String(describing: baseTheme)), ("accentColor", String(describing: accentColor)), ("outboxAccentColor", String(describing: outboxAccentColor)), ("messageColors", String(describing: messageColors)), ("wallpaper", String(describing: wallpaper))]) + case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let message, let entities): + return ("sponsoredMessage", [("flags", String(describing: flags)), ("randomId", String(describing: randomId)), ("fromId", String(describing: fromId)), ("chatInvite", String(describing: chatInvite)), ("chatInviteHash", String(describing: chatInviteHash)), ("channelPost", String(describing: channelPost)), ("startParam", String(describing: startParam)), ("message", String(describing: message)), ("entities", String(describing: entities))]) } } - public static func parse_themeSettings(_ reader: BufferReader) -> ThemeSettings? { + public static func parse_sponsoredMessage(_ reader: BufferReader) -> SponsoredMessage? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.BaseTheme? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.BaseTheme - } - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() } - var _5: [Int32]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Api.Peer? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer } } - var _6: Api.WallPaper? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.WallPaper + var _4: Api.ChatInvite? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.ChatInvite + } } + var _5: String? + if Int(_1!) & Int(1 << 4) != 0 {_5 = parseString(reader) } + var _6: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() } + var _7: String? + if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) } + var _8: String? + _8 = parseString(reader) + var _9: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) } } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.ThemeSettings.themeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6) + let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil + let _c8 = _8 != nil + let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, fromId: _3, chatInvite: _4, chatInviteHash: _5, channelPost: _6, startParam: _7, message: _8!, entities: _9) } else { return nil @@ -299,39 +469,37 @@ public extension Api { } } public extension Api { - enum TopPeer: TypeConstructorDescription { - case topPeer(peer: Api.Peer, rating: Double) + enum StatsAbsValueAndPrev: TypeConstructorDescription { + case statsAbsValueAndPrev(current: Double, previous: Double) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .topPeer(let peer, let rating): + case .statsAbsValueAndPrev(let current, let previous): if boxed { - buffer.appendInt32(-305282981) + buffer.appendInt32(-884757282) } - peer.serialize(buffer, true) - serializeDouble(rating, buffer: buffer, boxed: false) + serializeDouble(current, buffer: buffer, boxed: false) + serializeDouble(previous, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .topPeer(let peer, let rating): - return ("topPeer", [("peer", String(describing: peer)), ("rating", String(describing: rating))]) + case .statsAbsValueAndPrev(let current, let previous): + return ("statsAbsValueAndPrev", [("current", String(describing: current)), ("previous", String(describing: previous))]) } } - public static func parse_topPeer(_ reader: BufferReader) -> TopPeer? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } + public static func parse_statsAbsValueAndPrev(_ reader: BufferReader) -> StatsAbsValueAndPrev? { + var _1: Double? + _1 = reader.readDouble() var _2: Double? _2 = reader.readDouble() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.TopPeer.topPeer(peer: _1!, rating: _2!) + return Api.StatsAbsValueAndPrev.statsAbsValueAndPrev(current: _1!, previous: _2!) } else { return nil @@ -341,2896 +509,159 @@ public extension Api { } } public extension Api { - enum TopPeerCategory: TypeConstructorDescription { - case topPeerCategoryBotsInline - case topPeerCategoryBotsPM - case topPeerCategoryChannels - case topPeerCategoryCorrespondents - case topPeerCategoryForwardChats - case topPeerCategoryForwardUsers - case topPeerCategoryGroups - case topPeerCategoryPhoneCalls + enum StatsDateRangeDays: TypeConstructorDescription { + case statsDateRangeDays(minDate: Int32, maxDate: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .topPeerCategoryBotsInline: + case .statsDateRangeDays(let minDate, let maxDate): if boxed { - buffer.appendInt32(344356834) + buffer.appendInt32(-1237848657) } - - break - case .topPeerCategoryBotsPM: - if boxed { - buffer.appendInt32(-1419371685) - } - - break - case .topPeerCategoryChannels: - if boxed { - buffer.appendInt32(371037736) - } - - break - case .topPeerCategoryCorrespondents: - if boxed { - buffer.appendInt32(104314861) - } - - break - case .topPeerCategoryForwardChats: - if boxed { - buffer.appendInt32(-68239120) - } - - break - case .topPeerCategoryForwardUsers: - if boxed { - buffer.appendInt32(-1472172887) - } - - break - case .topPeerCategoryGroups: - if boxed { - buffer.appendInt32(-1122524854) - } - - break - case .topPeerCategoryPhoneCalls: - if boxed { - buffer.appendInt32(511092620) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .topPeerCategoryBotsInline: - return ("topPeerCategoryBotsInline", []) - case .topPeerCategoryBotsPM: - return ("topPeerCategoryBotsPM", []) - case .topPeerCategoryChannels: - return ("topPeerCategoryChannels", []) - case .topPeerCategoryCorrespondents: - return ("topPeerCategoryCorrespondents", []) - case .topPeerCategoryForwardChats: - return ("topPeerCategoryForwardChats", []) - case .topPeerCategoryForwardUsers: - return ("topPeerCategoryForwardUsers", []) - case .topPeerCategoryGroups: - return ("topPeerCategoryGroups", []) - case .topPeerCategoryPhoneCalls: - return ("topPeerCategoryPhoneCalls", []) - } - } - - public static func parse_topPeerCategoryBotsInline(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryBotsInline - } - public static func parse_topPeerCategoryBotsPM(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryBotsPM - } - public static func parse_topPeerCategoryChannels(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryChannels - } - public static func parse_topPeerCategoryCorrespondents(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryCorrespondents - } - public static func parse_topPeerCategoryForwardChats(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryForwardChats - } - public static func parse_topPeerCategoryForwardUsers(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryForwardUsers - } - public static func parse_topPeerCategoryGroups(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryGroups - } - public static func parse_topPeerCategoryPhoneCalls(_ reader: BufferReader) -> TopPeerCategory? { - return Api.TopPeerCategory.topPeerCategoryPhoneCalls - } - - } -} -public extension Api { - enum TopPeerCategoryPeers: TypeConstructorDescription { - case topPeerCategoryPeers(category: Api.TopPeerCategory, count: Int32, peers: [Api.TopPeer]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .topPeerCategoryPeers(let category, let count, let peers): - if boxed { - buffer.appendInt32(-75283823) - } - category.serialize(buffer, true) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .topPeerCategoryPeers(let category, let count, let peers): - return ("topPeerCategoryPeers", [("category", String(describing: category)), ("count", String(describing: count)), ("peers", String(describing: peers))]) - } - } - - public static func parse_topPeerCategoryPeers(_ reader: BufferReader) -> TopPeerCategoryPeers? { - var _1: Api.TopPeerCategory? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.TopPeerCategory - } - var _2: Int32? - _2 = reader.readInt32() - var _3: [Api.TopPeer]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.TopPeer.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.TopPeerCategoryPeers.topPeerCategoryPeers(category: _1!, count: _2!, peers: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Update: TypeConstructorDescription { - case updateAttachMenuBots - case updateBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, peer: Api.Peer, msgId: Int32, chatInstance: Int64, data: Buffer?, gameShortName: String?) - case updateBotChatInviteRequester(peer: Api.Peer, date: Int32, userId: Int64, about: String, invite: Api.ExportedChatInvite, qts: Int32) - case updateBotCommands(peer: Api.Peer, botId: Int64, commands: [Api.BotCommand]) - case updateBotInlineQuery(flags: Int32, queryId: Int64, userId: Int64, query: String, geo: Api.GeoPoint?, peerType: Api.InlineQueryPeerType?, offset: String) - case updateBotInlineSend(flags: Int32, userId: Int64, query: String, geo: Api.GeoPoint?, id: String, msgId: Api.InputBotInlineMessageID?) - case updateBotMenuButton(botId: Int64, button: Api.BotMenuButton) - case updateBotPrecheckoutQuery(flags: Int32, queryId: Int64, userId: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, currency: String, totalAmount: Int64) - case updateBotShippingQuery(queryId: Int64, userId: Int64, payload: Buffer, shippingAddress: Api.PostAddress) - case updateBotStopped(userId: Int64, date: Int32, stopped: Api.Bool, qts: Int32) - case updateBotWebhookJSON(data: Api.DataJSON) - case updateBotWebhookJSONQuery(queryId: Int64, data: Api.DataJSON, timeout: Int32) - case updateChannel(channelId: Int64) - case updateChannelAvailableMessages(channelId: Int64, availableMinId: Int32) - case updateChannelMessageForwards(channelId: Int64, id: Int32, forwards: Int32) - case updateChannelMessageViews(channelId: Int64, id: Int32, views: Int32) - case updateChannelParticipant(flags: Int32, channelId: Int64, date: Int32, actorId: Int64, userId: Int64, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) - case updateChannelReadMessagesContents(channelId: Int64, messages: [Int32]) - case updateChannelTooLong(flags: Int32, channelId: Int64, pts: Int32?) - case updateChannelUserTyping(flags: Int32, channelId: Int64, topMsgId: Int32?, fromId: Api.Peer, action: Api.SendMessageAction) - case updateChannelWebPage(channelId: Int64, webpage: Api.WebPage, pts: Int32, ptsCount: Int32) - case updateChat(chatId: Int64) - case updateChatDefaultBannedRights(peer: Api.Peer, defaultBannedRights: Api.ChatBannedRights, version: Int32) - case updateChatParticipant(flags: Int32, chatId: Int64, date: Int32, actorId: Int64, userId: Int64, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) - case updateChatParticipantAdd(chatId: Int64, userId: Int64, inviterId: Int64, date: Int32, version: Int32) - case updateChatParticipantAdmin(chatId: Int64, userId: Int64, isAdmin: Api.Bool, version: Int32) - case updateChatParticipantDelete(chatId: Int64, userId: Int64, version: Int32) - case updateChatParticipants(participants: Api.ChatParticipants) - case updateChatUserTyping(chatId: Int64, fromId: Api.Peer, action: Api.SendMessageAction) - case updateConfig - case updateContactsReset - case updateDcOptions(dcOptions: [Api.DcOption]) - case updateDeleteChannelMessages(channelId: Int64, messages: [Int32], pts: Int32, ptsCount: Int32) - case updateDeleteMessages(messages: [Int32], pts: Int32, ptsCount: Int32) - case updateDeleteScheduledMessages(peer: Api.Peer, messages: [Int32]) - case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) - case updateDialogFilterOrder(order: [Int32]) - case updateDialogFilters - case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer) - case updateDialogUnreadMark(flags: Int32, peer: Api.DialogPeer) - case updateDraftMessage(peer: Api.Peer, draft: Api.DraftMessage) - case updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) - case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32) - case updateEncryptedChatTyping(chatId: Int32) - case updateEncryptedMessagesRead(chatId: Int32, maxDate: Int32, date: Int32) - case updateEncryption(chat: Api.EncryptedChat, date: Int32) - case updateFavedStickers - case updateFolderPeers(folderPeers: [Api.FolderPeer], pts: Int32, ptsCount: Int32) - case updateGeoLiveViewed(peer: Api.Peer, msgId: Int32) - case updateGroupCall(chatId: Int64, call: Api.GroupCall) - case updateGroupCallConnection(flags: Int32, params: Api.DataJSON) - case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32) - case updateInlineBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, msgId: Api.InputBotInlineMessageID, chatInstance: Int64, data: Buffer?, gameShortName: String?) - case updateLangPack(difference: Api.LangPackDifference) - case updateLangPackTooLong(langCode: String) - case updateLoginToken - case updateMessageID(id: Int32, randomId: Int64) - case updateMessagePoll(flags: Int32, pollId: Int64, poll: Api.Poll?, results: Api.PollResults) - case updateMessagePollVote(pollId: Int64, userId: Int64, options: [Buffer], qts: Int32) - case updateMessageReactions(peer: Api.Peer, msgId: Int32, reactions: Api.MessageReactions) - case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) - case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32) - case updateNewMessage(message: Api.Message, pts: Int32, ptsCount: Int32) - case updateNewScheduledMessage(message: Api.Message) - case updateNewStickerSet(stickerset: Api.messages.StickerSet) - case updateNotifySettings(peer: Api.NotifyPeer, notifySettings: Api.PeerNotifySettings) - case updatePeerBlocked(peerId: Api.Peer, blocked: Api.Bool) - case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?) - case updatePeerLocated(peers: [Api.PeerLocated]) - case updatePeerSettings(peer: Api.Peer, settings: Api.PeerSettings) - case updatePendingJoinRequests(peer: Api.Peer, requestsPending: Int32, recentRequesters: [Int64]) - case updatePhoneCall(phoneCall: Api.PhoneCall) - case updatePhoneCallSignalingData(phoneCallId: Int64, data: Buffer) - case updatePinnedChannelMessages(flags: Int32, channelId: Int64, messages: [Int32], pts: Int32, ptsCount: Int32) - case updatePinnedDialogs(flags: Int32, folderId: Int32?, order: [Api.DialogPeer]?) - case updatePinnedMessages(flags: Int32, peer: Api.Peer, messages: [Int32], pts: Int32, ptsCount: Int32) - case updatePrivacy(key: Api.PrivacyKey, rules: [Api.PrivacyRule]) - case updatePtsChanged - case updateReadChannelDiscussionInbox(flags: Int32, channelId: Int64, topMsgId: Int32, readMaxId: Int32, broadcastId: Int64?, broadcastPost: Int32?) - case updateReadChannelDiscussionOutbox(channelId: Int64, topMsgId: Int32, readMaxId: Int32) - case updateReadChannelInbox(flags: Int32, folderId: Int32?, channelId: Int64, maxId: Int32, stillUnreadCount: Int32, pts: Int32) - case updateReadChannelOutbox(channelId: Int64, maxId: Int32) - case updateReadFeaturedStickers - case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32) - case updateReadHistoryOutbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32) - case updateReadMessagesContents(messages: [Int32], pts: Int32, ptsCount: Int32) - case updateRecentStickers - case updateSavedGifs - case updateSavedRingtones - case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity]) - case updateStickerSets - case updateStickerSetsOrder(flags: Int32, order: [Int64]) - case updateTheme(theme: Api.Theme) - case updateTranscribedAudio(flags: Int32, peer: Api.Peer, msgId: Int32, transcriptionId: Int64, text: String) - case updateUserName(userId: Int64, firstName: String, lastName: String, username: String) - case updateUserPhone(userId: Int64, phone: String) - case updateUserPhoto(userId: Int64, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool) - case updateUserStatus(userId: Int64, status: Api.UserStatus) - case updateUserTyping(userId: Int64, action: Api.SendMessageAction) - case updateWebPage(webpage: Api.WebPage, pts: Int32, ptsCount: Int32) - case updateWebViewResultSent(queryId: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .updateAttachMenuBots: - if boxed { - buffer.appendInt32(397910539) - } - - break - case .updateBotCallbackQuery(let flags, let queryId, let userId, let peer, let msgId, let chatInstance, let data, let gameShortName): - if boxed { - buffer.appendInt32(-1177566067) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt64(chatInstance, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(gameShortName!, buffer: buffer, boxed: false)} - break - case .updateBotChatInviteRequester(let peer, let date, let userId, let about, let invite, let qts): - if boxed { - buffer.appendInt32(299870598) - } - peer.serialize(buffer, true) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(about, buffer: buffer, boxed: false) - invite.serialize(buffer, true) - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateBotCommands(let peer, let botId, let commands): - if boxed { - buffer.appendInt32(1299263278) - } - peer.serialize(buffer, true) - serializeInt64(botId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(commands.count)) - for item in commands { - item.serialize(buffer, true) - } - break - case .updateBotInlineQuery(let flags, let queryId, let userId, let query, let geo, let peerType, let offset): - if boxed { - buffer.appendInt32(1232025500) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(query, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {geo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {peerType!.serialize(buffer, true)} - serializeString(offset, buffer: buffer, boxed: false) - break - case .updateBotInlineSend(let flags, let userId, let query, let geo, let id, let msgId): - if boxed { - buffer.appendInt32(317794823) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(query, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {geo!.serialize(buffer, true)} - serializeString(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {msgId!.serialize(buffer, true)} - break - case .updateBotMenuButton(let botId, let button): - if boxed { - buffer.appendInt32(347625491) - } - serializeInt64(botId, buffer: buffer, boxed: false) - button.serialize(buffer, true) - break - case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount): - if boxed { - buffer.appendInt32(-1934976362) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeBytes(payload, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(totalAmount, buffer: buffer, boxed: false) - break - case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): - if boxed { - buffer.appendInt32(-1246823043) - } - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeBytes(payload, buffer: buffer, boxed: false) - shippingAddress.serialize(buffer, true) - break - case .updateBotStopped(let userId, let date, let stopped, let qts): - if boxed { - buffer.appendInt32(-997782967) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - stopped.serialize(buffer, true) - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateBotWebhookJSON(let data): - if boxed { - buffer.appendInt32(-2095595325) - } - data.serialize(buffer, true) - break - case .updateBotWebhookJSONQuery(let queryId, let data, let timeout): - if boxed { - buffer.appendInt32(-1684914010) - } - serializeInt64(queryId, buffer: buffer, boxed: false) - data.serialize(buffer, true) - serializeInt32(timeout, buffer: buffer, boxed: false) - break - case .updateChannel(let channelId): - if boxed { - buffer.appendInt32(1666927625) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - break - case .updateChannelAvailableMessages(let channelId, let availableMinId): - if boxed { - buffer.appendInt32(-1304443240) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(availableMinId, buffer: buffer, boxed: false) - break - case .updateChannelMessageForwards(let channelId, let id, let forwards): - if boxed { - buffer.appendInt32(-761649164) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt32(forwards, buffer: buffer, boxed: false) - break - case .updateChannelMessageViews(let channelId, let id, let views): - if boxed { - buffer.appendInt32(-232346616) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt32(views, buffer: buffer, boxed: false) - break - case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): - if boxed { - buffer.appendInt32(-1738720581) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(actorId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)} - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateChannelReadMessagesContents(let channelId, let messages): - if boxed { - buffer.appendInt32(1153291573) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - break - case .updateChannelTooLong(let flags, let channelId, let pts): - if boxed { - buffer.appendInt32(277713951) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(channelId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(pts!, buffer: buffer, boxed: false)} - break - case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let fromId, let action): - if boxed { - buffer.appendInt32(-1937192669) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(channelId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} - fromId.serialize(buffer, true) - action.serialize(buffer, true) - break - case .updateChannelWebPage(let channelId, let webpage, let pts, let ptsCount): - if boxed { - buffer.appendInt32(791390623) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - webpage.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateChat(let chatId): - if boxed { - buffer.appendInt32(-124097970) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - break - case .updateChatDefaultBannedRights(let peer, let defaultBannedRights, let version): - if boxed { - buffer.appendInt32(1421875280) - } - peer.serialize(buffer, true) - defaultBannedRights.serialize(buffer, true) - serializeInt32(version, buffer: buffer, boxed: false) - break - case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): - if boxed { - buffer.appendInt32(-796432838) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(actorId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)} - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateChatParticipantAdd(let chatId, let userId, let inviterId, let date, let version): - if boxed { - buffer.appendInt32(1037718609) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt64(inviterId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(version, buffer: buffer, boxed: false) - break - case .updateChatParticipantAdmin(let chatId, let userId, let isAdmin, let version): - if boxed { - buffer.appendInt32(-674602590) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - isAdmin.serialize(buffer, true) - serializeInt32(version, buffer: buffer, boxed: false) - break - case .updateChatParticipantDelete(let chatId, let userId, let version): - if boxed { - buffer.appendInt32(-483443337) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(version, buffer: buffer, boxed: false) - break - case .updateChatParticipants(let participants): - if boxed { - buffer.appendInt32(125178264) - } - participants.serialize(buffer, true) - break - case .updateChatUserTyping(let chatId, let fromId, let action): - if boxed { - buffer.appendInt32(-2092401936) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - fromId.serialize(buffer, true) - action.serialize(buffer, true) - break - case .updateConfig: - if boxed { - buffer.appendInt32(-1574314746) - } - - break - case .updateContactsReset: - if boxed { - buffer.appendInt32(1887741886) - } - - break - case .updateDcOptions(let dcOptions): - if boxed { - buffer.appendInt32(-1906403213) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dcOptions.count)) - for item in dcOptions { - item.serialize(buffer, true) - } - break - case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-1020437742) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateDeleteMessages(let messages, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-1576161051) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateDeleteScheduledMessages(let peer, let messages): - if boxed { - buffer.appendInt32(-1870238482) - } - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - break - case .updateDialogFilter(let flags, let id, let filter): - if boxed { - buffer.appendInt32(654302845) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} - break - case .updateDialogFilterOrder(let order): - if boxed { - buffer.appendInt32(-1512627963) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order.count)) - for item in order { - serializeInt32(item, buffer: buffer, boxed: false) - } - break - case .updateDialogFilters: - if boxed { - buffer.appendInt32(889491791) - } - - break - case .updateDialogPinned(let flags, let folderId, let peer): - if boxed { - buffer.appendInt32(1852826908) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - peer.serialize(buffer, true) - break - case .updateDialogUnreadMark(let flags, let peer): - if boxed { - buffer.appendInt32(-513517117) - } - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - break - case .updateDraftMessage(let peer, let draft): - if boxed { - buffer.appendInt32(-299124375) - } - peer.serialize(buffer, true) - draft.serialize(buffer, true) - break - case .updateEditChannelMessage(let message, let pts, let ptsCount): - if boxed { - buffer.appendInt32(457133559) - } - message.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateEditMessage(let message, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-469536605) - } - message.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateEncryptedChatTyping(let chatId): - if boxed { - buffer.appendInt32(386986326) - } - serializeInt32(chatId, buffer: buffer, boxed: false) - break - case .updateEncryptedMessagesRead(let chatId, let maxDate, let date): - if boxed { - buffer.appendInt32(956179895) - } - serializeInt32(chatId, buffer: buffer, boxed: false) + serializeInt32(minDate, buffer: buffer, boxed: false) serializeInt32(maxDate, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .updateEncryption(let chat, let date): - if boxed { - buffer.appendInt32(-1264392051) - } - chat.serialize(buffer, true) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .updateFavedStickers: - if boxed { - buffer.appendInt32(-451831443) - } - - break - case .updateFolderPeers(let folderPeers, let pts, let ptsCount): - if boxed { - buffer.appendInt32(422972864) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(folderPeers.count)) - for item in folderPeers { - item.serialize(buffer, true) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateGeoLiveViewed(let peer, let msgId): - if boxed { - buffer.appendInt32(-2027964103) - } - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - break - case .updateGroupCall(let chatId, let call): - if boxed { - buffer.appendInt32(347227392) - } - serializeInt64(chatId, buffer: buffer, boxed: false) - call.serialize(buffer, true) - break - case .updateGroupCallConnection(let flags, let params): - if boxed { - buffer.appendInt32(192428418) - } - serializeInt32(flags, buffer: buffer, boxed: false) - params.serialize(buffer, true) - break - case .updateGroupCallParticipants(let call, let participants, let version): - if boxed { - buffer.appendInt32(-219423922) - } - call.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(participants.count)) - for item in participants { - item.serialize(buffer, true) - } - serializeInt32(version, buffer: buffer, boxed: false) - break - case .updateInlineBotCallbackQuery(let flags, let queryId, let userId, let msgId, let chatInstance, let data, let gameShortName): - if boxed { - buffer.appendInt32(1763610706) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - msgId.serialize(buffer, true) - serializeInt64(chatInstance, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(gameShortName!, buffer: buffer, boxed: false)} - break - case .updateLangPack(let difference): - if boxed { - buffer.appendInt32(1442983757) - } - difference.serialize(buffer, true) - break - case .updateLangPackTooLong(let langCode): - if boxed { - buffer.appendInt32(1180041828) - } - serializeString(langCode, buffer: buffer, boxed: false) - break - case .updateLoginToken: - if boxed { - buffer.appendInt32(1448076945) - } - - break - case .updateMessageID(let id, let randomId): - if boxed { - buffer.appendInt32(1318109142) - } - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt64(randomId, buffer: buffer, boxed: false) - break - case .updateMessagePoll(let flags, let pollId, let poll, let results): - if boxed { - buffer.appendInt32(-1398708869) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(pollId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {poll!.serialize(buffer, true)} - results.serialize(buffer, true) - break - case .updateMessagePollVote(let pollId, let userId, let options, let qts): - if boxed { - buffer.appendInt32(274961865) - } - serializeInt64(pollId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(options.count)) - for item in options { - serializeBytes(item, buffer: buffer, boxed: false) - } - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateMessageReactions(let peer, let msgId, let reactions): - if boxed { - buffer.appendInt32(357013699) - } - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - reactions.serialize(buffer, true) - break - case .updateNewChannelMessage(let message, let pts, let ptsCount): - if boxed { - buffer.appendInt32(1656358105) - } - message.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateNewEncryptedMessage(let message, let qts): - if boxed { - buffer.appendInt32(314359194) - } - message.serialize(buffer, true) - serializeInt32(qts, buffer: buffer, boxed: false) - break - case .updateNewMessage(let message, let pts, let ptsCount): - if boxed { - buffer.appendInt32(522914557) - } - message.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateNewScheduledMessage(let message): - if boxed { - buffer.appendInt32(967122427) - } - message.serialize(buffer, true) - break - case .updateNewStickerSet(let stickerset): - if boxed { - buffer.appendInt32(1753886890) - } - stickerset.serialize(buffer, true) - break - case .updateNotifySettings(let peer, let notifySettings): - if boxed { - buffer.appendInt32(-1094555409) - } - peer.serialize(buffer, true) - notifySettings.serialize(buffer, true) - break - case .updatePeerBlocked(let peerId, let blocked): - if boxed { - buffer.appendInt32(610945826) - } - peerId.serialize(buffer, true) - blocked.serialize(buffer, true) - break - case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod): - if boxed { - buffer.appendInt32(-1147422299) - } - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - case .updatePeerLocated(let peers): - if boxed { - buffer.appendInt32(-1263546448) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { - item.serialize(buffer, true) - } - break - case .updatePeerSettings(let peer, let settings): - if boxed { - buffer.appendInt32(1786671974) - } - peer.serialize(buffer, true) - settings.serialize(buffer, true) - break - case .updatePendingJoinRequests(let peer, let requestsPending, let recentRequesters): - if boxed { - buffer.appendInt32(1885586395) - } - peer.serialize(buffer, true) - serializeInt32(requestsPending, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(recentRequesters.count)) - for item in recentRequesters { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .updatePhoneCall(let phoneCall): - if boxed { - buffer.appendInt32(-1425052898) - } - phoneCall.serialize(buffer, true) - break - case .updatePhoneCallSignalingData(let phoneCallId, let data): - if boxed { - buffer.appendInt32(643940105) - } - serializeInt64(phoneCallId, buffer: buffer, boxed: false) - serializeBytes(data, buffer: buffer, boxed: false) - break - case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount): - if boxed { - buffer.appendInt32(1538885128) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(channelId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updatePinnedDialogs(let flags, let folderId, let order): - if boxed { - buffer.appendInt32(-99664734) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order!.count)) - for item in order! { - item.serialize(buffer, true) - }} - break - case .updatePinnedMessages(let flags, let peer, let messages, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-309990731) - } - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updatePrivacy(let key, let rules): - if boxed { - buffer.appendInt32(-298113238) - } - key.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rules.count)) - for item in rules { - item.serialize(buffer, true) - } - break - case .updatePtsChanged: - if boxed { - buffer.appendInt32(861169551) - } - - break - case .updateReadChannelDiscussionInbox(let flags, let channelId, let topMsgId, let readMaxId, let broadcastId, let broadcastPost): - if boxed { - buffer.appendInt32(-693004986) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(topMsgId, buffer: buffer, boxed: false) - serializeInt32(readMaxId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt64(broadcastId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(broadcastPost!, buffer: buffer, boxed: false)} - break - case .updateReadChannelDiscussionOutbox(let channelId, let topMsgId, let readMaxId): - if boxed { - buffer.appendInt32(1767677564) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(topMsgId, buffer: buffer, boxed: false) - serializeInt32(readMaxId, buffer: buffer, boxed: false) - break - case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): - if boxed { - buffer.appendInt32(-1842450928) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - break - case .updateReadChannelOutbox(let channelId, let maxId): - if boxed { - buffer.appendInt32(-1218471511) - } - serializeInt64(channelId, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - break - case .updateReadFeaturedStickers: - if boxed { - buffer.appendInt32(1461528386) - } - - break - case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-1667805217) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - peer.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): - if boxed { - buffer.appendInt32(791617983) - } - peer.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateReadMessagesContents(let messages, let pts, let ptsCount): - if boxed { - buffer.appendInt32(1757493555) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateRecentStickers: - if boxed { - buffer.appendInt32(-1706939360) - } - - break - case .updateSavedGifs: - if boxed { - buffer.appendInt32(-1821035490) - } - - break - case .updateSavedRingtones: - if boxed { - buffer.appendInt32(1960361625) - } - - break - case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities): - if boxed { - buffer.appendInt32(-337352679) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(inboxDate!, buffer: buffer, boxed: false)} - serializeString(type, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - media.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities.count)) - for item in entities { - item.serialize(buffer, true) - } - break - case .updateStickerSets: - if boxed { - buffer.appendInt32(1135492588) - } - - break - case .updateStickerSetsOrder(let flags, let order): - if boxed { - buffer.appendInt32(196268545) - } - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order.count)) - for item in order { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .updateTheme(let theme): - if boxed { - buffer.appendInt32(-2112423005) - } - theme.serialize(buffer, true) - break - case .updateTranscribedAudio(let flags, let peer, let msgId, let transcriptionId, let text): - if boxed { - buffer.appendInt32(8703322) - } - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt64(transcriptionId, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - break - case .updateUserName(let userId, let firstName, let lastName, let username): - if boxed { - buffer.appendInt32(-1007549728) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(firstName, buffer: buffer, boxed: false) - serializeString(lastName, buffer: buffer, boxed: false) - serializeString(username, buffer: buffer, boxed: false) - break - case .updateUserPhone(let userId, let phone): - if boxed { - buffer.appendInt32(88680979) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(phone, buffer: buffer, boxed: false) - break - case .updateUserPhoto(let userId, let date, let photo, let previous): - if boxed { - buffer.appendInt32(-232290676) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - photo.serialize(buffer, true) - previous.serialize(buffer, true) - break - case .updateUserStatus(let userId, let status): - if boxed { - buffer.appendInt32(-440534818) - } - serializeInt64(userId, buffer: buffer, boxed: false) - status.serialize(buffer, true) - break - case .updateUserTyping(let userId, let action): - if boxed { - buffer.appendInt32(-1071741569) - } - serializeInt64(userId, buffer: buffer, boxed: false) - action.serialize(buffer, true) - break - case .updateWebPage(let webpage, let pts, let ptsCount): - if boxed { - buffer.appendInt32(2139689491) - } - webpage.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - case .updateWebViewResultSent(let queryId): - if boxed { - buffer.appendInt32(361936797) - } - serializeInt64(queryId, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .updateAttachMenuBots: - return ("updateAttachMenuBots", []) - case .updateBotCallbackQuery(let flags, let queryId, let userId, let peer, let msgId, let chatInstance, let data, let gameShortName): - return ("updateBotCallbackQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("chatInstance", String(describing: chatInstance)), ("data", String(describing: data)), ("gameShortName", String(describing: gameShortName))]) - case .updateBotChatInviteRequester(let peer, let date, let userId, let about, let invite, let qts): - return ("updateBotChatInviteRequester", [("peer", String(describing: peer)), ("date", String(describing: date)), ("userId", String(describing: userId)), ("about", String(describing: about)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) - case .updateBotCommands(let peer, let botId, let commands): - return ("updateBotCommands", [("peer", String(describing: peer)), ("botId", String(describing: botId)), ("commands", String(describing: commands))]) - case .updateBotInlineQuery(let flags, let queryId, let userId, let query, let geo, let peerType, let offset): - return ("updateBotInlineQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("query", String(describing: query)), ("geo", String(describing: geo)), ("peerType", String(describing: peerType)), ("offset", String(describing: offset))]) - case .updateBotInlineSend(let flags, let userId, let query, let geo, let id, let msgId): - return ("updateBotInlineSend", [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("query", String(describing: query)), ("geo", String(describing: geo)), ("id", String(describing: id)), ("msgId", String(describing: msgId))]) - case .updateBotMenuButton(let botId, let button): - return ("updateBotMenuButton", [("botId", String(describing: botId)), ("button", String(describing: button))]) - case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount): - return ("updateBotPrecheckoutQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("payload", String(describing: payload)), ("info", String(describing: info)), ("shippingOptionId", String(describing: shippingOptionId)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount))]) - case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): - return ("updateBotShippingQuery", [("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("payload", String(describing: payload)), ("shippingAddress", String(describing: shippingAddress))]) - case .updateBotStopped(let userId, let date, let stopped, let qts): - return ("updateBotStopped", [("userId", String(describing: userId)), ("date", String(describing: date)), ("stopped", String(describing: stopped)), ("qts", String(describing: qts))]) - case .updateBotWebhookJSON(let data): - return ("updateBotWebhookJSON", [("data", String(describing: data))]) - case .updateBotWebhookJSONQuery(let queryId, let data, let timeout): - return ("updateBotWebhookJSONQuery", [("queryId", String(describing: queryId)), ("data", String(describing: data)), ("timeout", String(describing: timeout))]) - case .updateChannel(let channelId): - return ("updateChannel", [("channelId", String(describing: channelId))]) - case .updateChannelAvailableMessages(let channelId, let availableMinId): - return ("updateChannelAvailableMessages", [("channelId", String(describing: channelId)), ("availableMinId", String(describing: availableMinId))]) - case .updateChannelMessageForwards(let channelId, let id, let forwards): - return ("updateChannelMessageForwards", [("channelId", String(describing: channelId)), ("id", String(describing: id)), ("forwards", String(describing: forwards))]) - case .updateChannelMessageViews(let channelId, let id, let views): - return ("updateChannelMessageViews", [("channelId", String(describing: channelId)), ("id", String(describing: id)), ("views", String(describing: views))]) - case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): - return ("updateChannelParticipant", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("date", String(describing: date)), ("actorId", String(describing: actorId)), ("userId", String(describing: userId)), ("prevParticipant", String(describing: prevParticipant)), ("newParticipant", String(describing: newParticipant)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) - case .updateChannelReadMessagesContents(let channelId, let messages): - return ("updateChannelReadMessagesContents", [("channelId", String(describing: channelId)), ("messages", String(describing: messages))]) - case .updateChannelTooLong(let flags, let channelId, let pts): - return ("updateChannelTooLong", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("pts", String(describing: pts))]) - case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let fromId, let action): - return ("updateChannelUserTyping", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("fromId", String(describing: fromId)), ("action", String(describing: action))]) - case .updateChannelWebPage(let channelId, let webpage, let pts, let ptsCount): - return ("updateChannelWebPage", [("channelId", String(describing: channelId)), ("webpage", String(describing: webpage)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateChat(let chatId): - return ("updateChat", [("chatId", String(describing: chatId))]) - case .updateChatDefaultBannedRights(let peer, let defaultBannedRights, let version): - return ("updateChatDefaultBannedRights", [("peer", String(describing: peer)), ("defaultBannedRights", String(describing: defaultBannedRights)), ("version", String(describing: version))]) - case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): - return ("updateChatParticipant", [("flags", String(describing: flags)), ("chatId", String(describing: chatId)), ("date", String(describing: date)), ("actorId", String(describing: actorId)), ("userId", String(describing: userId)), ("prevParticipant", String(describing: prevParticipant)), ("newParticipant", String(describing: newParticipant)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) - case .updateChatParticipantAdd(let chatId, let userId, let inviterId, let date, let version): - return ("updateChatParticipantAdd", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("inviterId", String(describing: inviterId)), ("date", String(describing: date)), ("version", String(describing: version))]) - case .updateChatParticipantAdmin(let chatId, let userId, let isAdmin, let version): - return ("updateChatParticipantAdmin", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("isAdmin", String(describing: isAdmin)), ("version", String(describing: version))]) - case .updateChatParticipantDelete(let chatId, let userId, let version): - return ("updateChatParticipantDelete", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("version", String(describing: version))]) - case .updateChatParticipants(let participants): - return ("updateChatParticipants", [("participants", String(describing: participants))]) - case .updateChatUserTyping(let chatId, let fromId, let action): - return ("updateChatUserTyping", [("chatId", String(describing: chatId)), ("fromId", String(describing: fromId)), ("action", String(describing: action))]) - case .updateConfig: - return ("updateConfig", []) - case .updateContactsReset: - return ("updateContactsReset", []) - case .updateDcOptions(let dcOptions): - return ("updateDcOptions", [("dcOptions", String(describing: dcOptions))]) - case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): - return ("updateDeleteChannelMessages", [("channelId", String(describing: channelId)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateDeleteMessages(let messages, let pts, let ptsCount): - return ("updateDeleteMessages", [("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateDeleteScheduledMessages(let peer, let messages): - return ("updateDeleteScheduledMessages", [("peer", String(describing: peer)), ("messages", String(describing: messages))]) - case .updateDialogFilter(let flags, let id, let filter): - return ("updateDialogFilter", [("flags", String(describing: flags)), ("id", String(describing: id)), ("filter", String(describing: filter))]) - case .updateDialogFilterOrder(let order): - return ("updateDialogFilterOrder", [("order", String(describing: order))]) - case .updateDialogFilters: - return ("updateDialogFilters", []) - case .updateDialogPinned(let flags, let folderId, let peer): - return ("updateDialogPinned", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer))]) - case .updateDialogUnreadMark(let flags, let peer): - return ("updateDialogUnreadMark", [("flags", String(describing: flags)), ("peer", String(describing: peer))]) - case .updateDraftMessage(let peer, let draft): - return ("updateDraftMessage", [("peer", String(describing: peer)), ("draft", String(describing: draft))]) - case .updateEditChannelMessage(let message, let pts, let ptsCount): - return ("updateEditChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateEditMessage(let message, let pts, let ptsCount): - return ("updateEditMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateEncryptedChatTyping(let chatId): - return ("updateEncryptedChatTyping", [("chatId", String(describing: chatId))]) - case .updateEncryptedMessagesRead(let chatId, let maxDate, let date): - return ("updateEncryptedMessagesRead", [("chatId", String(describing: chatId)), ("maxDate", String(describing: maxDate)), ("date", String(describing: date))]) - case .updateEncryption(let chat, let date): - return ("updateEncryption", [("chat", String(describing: chat)), ("date", String(describing: date))]) - case .updateFavedStickers: - return ("updateFavedStickers", []) - case .updateFolderPeers(let folderPeers, let pts, let ptsCount): - return ("updateFolderPeers", [("folderPeers", String(describing: folderPeers)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateGeoLiveViewed(let peer, let msgId): - return ("updateGeoLiveViewed", [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]) - case .updateGroupCall(let chatId, let call): - return ("updateGroupCall", [("chatId", String(describing: chatId)), ("call", String(describing: call))]) - case .updateGroupCallConnection(let flags, let params): - return ("updateGroupCallConnection", [("flags", String(describing: flags)), ("params", String(describing: params))]) - case .updateGroupCallParticipants(let call, let participants, let version): - return ("updateGroupCallParticipants", [("call", String(describing: call)), ("participants", String(describing: participants)), ("version", String(describing: version))]) - case .updateInlineBotCallbackQuery(let flags, let queryId, let userId, let msgId, let chatInstance, let data, let gameShortName): - return ("updateInlineBotCallbackQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("msgId", String(describing: msgId)), ("chatInstance", String(describing: chatInstance)), ("data", String(describing: data)), ("gameShortName", String(describing: gameShortName))]) - case .updateLangPack(let difference): - return ("updateLangPack", [("difference", String(describing: difference))]) - case .updateLangPackTooLong(let langCode): - return ("updateLangPackTooLong", [("langCode", String(describing: langCode))]) - case .updateLoginToken: - return ("updateLoginToken", []) - case .updateMessageID(let id, let randomId): - return ("updateMessageID", [("id", String(describing: id)), ("randomId", String(describing: randomId))]) - case .updateMessagePoll(let flags, let pollId, let poll, let results): - return ("updateMessagePoll", [("flags", String(describing: flags)), ("pollId", String(describing: pollId)), ("poll", String(describing: poll)), ("results", String(describing: results))]) - case .updateMessagePollVote(let pollId, let userId, let options, let qts): - return ("updateMessagePollVote", [("pollId", String(describing: pollId)), ("userId", String(describing: userId)), ("options", String(describing: options)), ("qts", String(describing: qts))]) - case .updateMessageReactions(let peer, let msgId, let reactions): - return ("updateMessageReactions", [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reactions", String(describing: reactions))]) - case .updateNewChannelMessage(let message, let pts, let ptsCount): - return ("updateNewChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateNewEncryptedMessage(let message, let qts): - return ("updateNewEncryptedMessage", [("message", String(describing: message)), ("qts", String(describing: qts))]) - case .updateNewMessage(let message, let pts, let ptsCount): - return ("updateNewMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateNewScheduledMessage(let message): - return ("updateNewScheduledMessage", [("message", String(describing: message))]) - case .updateNewStickerSet(let stickerset): - return ("updateNewStickerSet", [("stickerset", String(describing: stickerset))]) - case .updateNotifySettings(let peer, let notifySettings): - return ("updateNotifySettings", [("peer", String(describing: peer)), ("notifySettings", String(describing: notifySettings))]) - case .updatePeerBlocked(let peerId, let blocked): - return ("updatePeerBlocked", [("peerId", String(describing: peerId)), ("blocked", String(describing: blocked))]) - case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod): - return ("updatePeerHistoryTTL", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("ttlPeriod", String(describing: ttlPeriod))]) - case .updatePeerLocated(let peers): - return ("updatePeerLocated", [("peers", String(describing: peers))]) - case .updatePeerSettings(let peer, let settings): - return ("updatePeerSettings", [("peer", String(describing: peer)), ("settings", String(describing: settings))]) - case .updatePendingJoinRequests(let peer, let requestsPending, let recentRequesters): - return ("updatePendingJoinRequests", [("peer", String(describing: peer)), ("requestsPending", String(describing: requestsPending)), ("recentRequesters", String(describing: recentRequesters))]) - case .updatePhoneCall(let phoneCall): - return ("updatePhoneCall", [("phoneCall", String(describing: phoneCall))]) - case .updatePhoneCallSignalingData(let phoneCallId, let data): - return ("updatePhoneCallSignalingData", [("phoneCallId", String(describing: phoneCallId)), ("data", String(describing: data))]) - case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount): - return ("updatePinnedChannelMessages", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updatePinnedDialogs(let flags, let folderId, let order): - return ("updatePinnedDialogs", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("order", String(describing: order))]) - case .updatePinnedMessages(let flags, let peer, let messages, let pts, let ptsCount): - return ("updatePinnedMessages", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updatePrivacy(let key, let rules): - return ("updatePrivacy", [("key", String(describing: key)), ("rules", String(describing: rules))]) - case .updatePtsChanged: - return ("updatePtsChanged", []) - case .updateReadChannelDiscussionInbox(let flags, let channelId, let topMsgId, let readMaxId, let broadcastId, let broadcastPost): - return ("updateReadChannelDiscussionInbox", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("readMaxId", String(describing: readMaxId)), ("broadcastId", String(describing: broadcastId)), ("broadcastPost", String(describing: broadcastPost))]) - case .updateReadChannelDiscussionOutbox(let channelId, let topMsgId, let readMaxId): - return ("updateReadChannelDiscussionOutbox", [("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("readMaxId", String(describing: readMaxId))]) - case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): - return ("updateReadChannelInbox", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("channelId", String(describing: channelId)), ("maxId", String(describing: maxId)), ("stillUnreadCount", String(describing: stillUnreadCount)), ("pts", String(describing: pts))]) - case .updateReadChannelOutbox(let channelId, let maxId): - return ("updateReadChannelOutbox", [("channelId", String(describing: channelId)), ("maxId", String(describing: maxId))]) - case .updateReadFeaturedStickers: - return ("updateReadFeaturedStickers", []) - case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): - return ("updateReadHistoryInbox", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("stillUnreadCount", String(describing: stillUnreadCount)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): - return ("updateReadHistoryOutbox", [("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateReadMessagesContents(let messages, let pts, let ptsCount): - return ("updateReadMessagesContents", [("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateRecentStickers: - return ("updateRecentStickers", []) - case .updateSavedGifs: - return ("updateSavedGifs", []) - case .updateSavedRingtones: - return ("updateSavedRingtones", []) - case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities): - return ("updateServiceNotification", [("flags", String(describing: flags)), ("inboxDate", String(describing: inboxDate)), ("type", String(describing: type)), ("message", String(describing: message)), ("media", String(describing: media)), ("entities", String(describing: entities))]) - case .updateStickerSets: - return ("updateStickerSets", []) - case .updateStickerSetsOrder(let flags, let order): - return ("updateStickerSetsOrder", [("flags", String(describing: flags)), ("order", String(describing: order))]) - case .updateTheme(let theme): - return ("updateTheme", [("theme", String(describing: theme))]) - case .updateTranscribedAudio(let flags, let peer, let msgId, let transcriptionId, let text): - return ("updateTranscribedAudio", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("transcriptionId", String(describing: transcriptionId)), ("text", String(describing: text))]) - case .updateUserName(let userId, let firstName, let lastName, let username): - return ("updateUserName", [("userId", String(describing: userId)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username))]) - case .updateUserPhone(let userId, let phone): - return ("updateUserPhone", [("userId", String(describing: userId)), ("phone", String(describing: phone))]) - case .updateUserPhoto(let userId, let date, let photo, let previous): - return ("updateUserPhoto", [("userId", String(describing: userId)), ("date", String(describing: date)), ("photo", String(describing: photo)), ("previous", String(describing: previous))]) - case .updateUserStatus(let userId, let status): - return ("updateUserStatus", [("userId", String(describing: userId)), ("status", String(describing: status))]) - case .updateUserTyping(let userId, let action): - return ("updateUserTyping", [("userId", String(describing: userId)), ("action", String(describing: action))]) - case .updateWebPage(let webpage, let pts, let ptsCount): - return ("updateWebPage", [("webpage", String(describing: webpage)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - case .updateWebViewResultSent(let queryId): - return ("updateWebViewResultSent", [("queryId", String(describing: queryId))]) + case .statsDateRangeDays(let minDate, let maxDate): + return ("statsDateRangeDays", [("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]) } } - public static func parse_updateAttachMenuBots(_ reader: BufferReader) -> Update? { - return Api.Update.updateAttachMenuBots - } - public static func parse_updateBotCallbackQuery(_ reader: BufferReader) -> Update? { + public static func parse_statsDateRangeDays(_ reader: BufferReader) -> StatsDateRangeDays? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Api.Peer? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _5: Int32? - _5 = reader.readInt32() - var _6: Int64? - _6 = reader.readInt64() - var _7: Buffer? - if Int(_1!) & Int(1 << 0) != 0 {_7 = parseBytes(reader) } - var _8: String? - if Int(_1!) & Int(1 << 1) != 0 {_8 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.Update.updateBotCallbackQuery(flags: _1!, queryId: _2!, userId: _3!, peer: _4!, msgId: _5!, chatInstance: _6!, data: _7, gameShortName: _8) - } - else { - return nil - } - } - public static func parse_updateBotChatInviteRequester(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } var _2: Int32? _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - var _6: Int32? - _6 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Update.updateBotChatInviteRequester(peer: _1!, date: _2!, userId: _3!, about: _4!, invite: _5!, qts: _6!) + if _c1 && _c2 { + return Api.StatsDateRangeDays.statsDateRangeDays(minDate: _1!, maxDate: _2!) } else { return nil } } - public static func parse_updateBotCommands(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int64? - _2 = reader.readInt64() - var _3: [Api.BotCommand]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateBotCommands(peer: _1!, botId: _2!, commands: _3!) - } - else { - return nil - } - } - public static func parse_updateBotInlineQuery(_ reader: BufferReader) -> Update? { + + } +} +public extension Api { + enum StatsGraph: TypeConstructorDescription { + case statsGraph(flags: Int32, json: Api.DataJSON, zoomToken: String?) + case statsGraphAsync(token: String) + case statsGraphError(error: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGraph(let flags, let json, let zoomToken): + if boxed { + buffer.appendInt32(-1901828938) + } + serializeInt32(flags, buffer: buffer, boxed: false) + json.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeString(zoomToken!, buffer: buffer, boxed: false)} + break + case .statsGraphAsync(let token): + if boxed { + buffer.appendInt32(1244130093) + } + serializeString(token, buffer: buffer, boxed: false) + break + case .statsGraphError(let error): + if boxed { + buffer.appendInt32(-1092839390) + } + serializeString(error, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGraph(let flags, let json, let zoomToken): + return ("statsGraph", [("flags", String(describing: flags)), ("json", String(describing: json)), ("zoomToken", String(describing: zoomToken))]) + case .statsGraphAsync(let token): + return ("statsGraphAsync", [("token", String(describing: token))]) + case .statsGraphError(let error): + return ("statsGraphError", [("error", String(describing: error))]) + } + } + + public static func parse_statsGraph(_ reader: BufferReader) -> StatsGraph? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: Api.GeoPoint? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } } - var _6: Api.InlineQueryPeerType? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.InlineQueryPeerType - } } - var _7: String? - _7 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.Update.updateBotInlineQuery(flags: _1!, queryId: _2!, userId: _3!, query: _4!, geo: _5, peerType: _6, offset: _7!) + var _2: Api.DataJSON? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DataJSON } - else { - return nil - } - } - public static func parse_updateBotInlineSend(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() var _3: String? - _3 = parseString(reader) - var _4: Api.GeoPoint? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } } - var _5: String? - _5 = parseString(reader) - var _6: Api.InputBotInlineMessageID? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID - } } - 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 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Update.updateBotInlineSend(flags: _1!, userId: _2!, query: _3!, geo: _4, id: _5!, msgId: _6) - } - else { - return nil - } - } - public static func parse_updateBotMenuButton(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.BotMenuButton? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.BotMenuButton - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateBotMenuButton(botId: _1!, button: _2!) - } - else { - return nil - } - } - public static func parse_updateBotPrecheckoutQuery(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Buffer? - _4 = parseBytes(reader) - var _5: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - var _6: String? - if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } - var _7: String? - _7 = parseString(reader) - var _8: Int64? - _8 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.Update.updateBotPrecheckoutQuery(flags: _1!, queryId: _2!, userId: _3!, payload: _4!, info: _5, shippingOptionId: _6, currency: _7!, totalAmount: _8!) - } - else { - return nil - } - } - public static func parse_updateBotShippingQuery(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Buffer? - _3 = parseBytes(reader) - var _4: Api.PostAddress? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.PostAddress - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateBotShippingQuery(queryId: _1!, userId: _2!, payload: _3!, shippingAddress: _4!) - } - else { - return nil - } - } - public static func parse_updateBotStopped(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.Bool? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Bool - } - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateBotStopped(userId: _1!, date: _2!, stopped: _3!, qts: _4!) - } - else { - return nil - } - } - public static func parse_updateBotWebhookJSON(_ reader: BufferReader) -> Update? { - var _1: Api.DataJSON? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateBotWebhookJSON(data: _1!) - } - else { - return nil - } - } - public static func parse_updateBotWebhookJSONQuery(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.DataJSON? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateBotWebhookJSONQuery(queryId: _1!, data: _2!, timeout: _3!) - } - else { - return nil - } - } - public static func parse_updateChannel(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateChannel(channelId: _1!) - } - else { - return nil - } - } - public static func parse_updateChannelAvailableMessages(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateChannelAvailableMessages(channelId: _1!, availableMinId: _2!) - } - else { - return nil - } - } - public static func parse_updateChannelMessageForwards(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateChannelMessageForwards(channelId: _1!, id: _2!, forwards: _3!) - } - else { - return nil - } - } - public static func parse_updateChannelMessageViews(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateChannelMessageViews(channelId: _1!, id: _2!, views: _3!) - } - else { - return nil - } - } - public static func parse_updateChannelParticipant(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int64? - _4 = reader.readInt64() - var _5: Int64? - _5 = reader.readInt64() - var _6: Api.ChannelParticipant? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant - } } - var _7: Api.ChannelParticipant? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant - } } - var _8: Api.ExportedChatInvite? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } } - var _9: Int32? - _9 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil - let _c9 = _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.Update.updateChannelParticipant(flags: _1!, channelId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!) - } - else { - return nil - } - } - public static func parse_updateChannelReadMessagesContents(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Int32]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateChannelReadMessagesContents(channelId: _1!, messages: _2!) - } - else { - return nil - } - } - public static func parse_updateChannelTooLong(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil if _c1 && _c2 && _c3 { - return Api.Update.updateChannelTooLong(flags: _1!, channelId: _2!, pts: _3) + return Api.StatsGraph.statsGraph(flags: _1!, json: _2!, zoomToken: _3) } else { return nil } } - public static func parse_updateChannelUserTyping(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - var _4: Api.Peer? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _5: Api.SendMessageAction? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.SendMessageAction - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Update.updateChannelUserTyping(flags: _1!, channelId: _2!, topMsgId: _3, fromId: _4!, action: _5!) - } - else { - return nil - } - } - public static func parse_updateChannelWebPage(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.WebPage? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.WebPage - } - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateChannelWebPage(channelId: _1!, webpage: _2!, pts: _3!, ptsCount: _4!) - } - else { - return nil - } - } - public static func parse_updateChat(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateChat(chatId: _1!) - } - else { - return nil - } - } - public static func parse_updateChatDefaultBannedRights(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Api.ChatBannedRights? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.ChatBannedRights - } - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateChatDefaultBannedRights(peer: _1!, defaultBannedRights: _2!, version: _3!) - } - else { - return nil - } - } - public static func parse_updateChatParticipant(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int64? - _4 = reader.readInt64() - var _5: Int64? - _5 = reader.readInt64() - var _6: Api.ChatParticipant? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.ChatParticipant - } } - var _7: Api.ChatParticipant? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.ChatParticipant - } } - var _8: Api.ExportedChatInvite? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } } - var _9: Int32? - _9 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil - let _c9 = _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.Update.updateChatParticipant(flags: _1!, chatId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!) - } - else { - return nil - } - } - public static func parse_updateChatParticipantAdd(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Update.updateChatParticipantAdd(chatId: _1!, userId: _2!, inviterId: _3!, date: _4!, version: _5!) - } - else { - return nil - } - } - public static func parse_updateChatParticipantAdmin(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.Bool? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Bool - } - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateChatParticipantAdmin(chatId: _1!, userId: _2!, isAdmin: _3!, version: _4!) - } - else { - return nil - } - } - public static func parse_updateChatParticipantDelete(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateChatParticipantDelete(chatId: _1!, userId: _2!, version: _3!) - } - else { - return nil - } - } - public static func parse_updateChatParticipants(_ reader: BufferReader) -> Update? { - var _1: Api.ChatParticipants? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.ChatParticipants - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateChatParticipants(participants: _1!) - } - else { - return nil - } - } - public static func parse_updateChatUserTyping(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.Peer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _3: Api.SendMessageAction? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.SendMessageAction - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateChatUserTyping(chatId: _1!, fromId: _2!, action: _3!) - } - else { - return nil - } - } - public static func parse_updateConfig(_ reader: BufferReader) -> Update? { - return Api.Update.updateConfig - } - public static func parse_updateContactsReset(_ reader: BufferReader) -> Update? { - return Api.Update.updateContactsReset - } - public static func parse_updateDcOptions(_ reader: BufferReader) -> Update? { - var _1: [Api.DcOption]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DcOption.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateDcOptions(dcOptions: _1!) - } - else { - return nil - } - } - public static func parse_updateDeleteChannelMessages(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Int32]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateDeleteChannelMessages(channelId: _1!, messages: _2!, pts: _3!, ptsCount: _4!) - } - else { - return nil - } - } - public static func parse_updateDeleteMessages(_ reader: BufferReader) -> Update? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateDeleteMessages(messages: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateDeleteScheduledMessages(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: [Int32]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateDeleteScheduledMessages(peer: _1!, messages: _2!) - } - else { - return nil - } - } - public static func parse_updateDialogFilter(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.DialogFilter? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.DialogFilter - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateDialogFilter(flags: _1!, id: _2!, filter: _3) - } - else { - return nil - } - } - public static func parse_updateDialogFilterOrder(_ reader: BufferReader) -> Update? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateDialogFilterOrder(order: _1!) - } - else { - return nil - } - } - public static func parse_updateDialogFilters(_ reader: BufferReader) -> Update? { - return Api.Update.updateDialogFilters - } - public static func parse_updateDialogPinned(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: Api.DialogPeer? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.DialogPeer - } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateDialogPinned(flags: _1!, folderId: _2, peer: _3!) - } - else { - return nil - } - } - public static func parse_updateDialogUnreadMark(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.DialogPeer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DialogPeer - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateDialogUnreadMark(flags: _1!, peer: _2!) - } - else { - return nil - } - } - public static func parse_updateDraftMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Api.DraftMessage? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DraftMessage - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateDraftMessage(peer: _1!, draft: _2!) - } - else { - return nil - } - } - public static func parse_updateEditChannelMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Message? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Message - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateEditChannelMessage(message: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateEditMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Message? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Message - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateEditMessage(message: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateEncryptedChatTyping(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateEncryptedChatTyping(chatId: _1!) - } - else { - return nil - } - } - public static func parse_updateEncryptedMessagesRead(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateEncryptedMessagesRead(chatId: _1!, maxDate: _2!, date: _3!) - } - else { - return nil - } - } - public static func parse_updateEncryption(_ reader: BufferReader) -> Update? { - var _1: Api.EncryptedChat? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.EncryptedChat - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateEncryption(chat: _1!, date: _2!) - } - else { - return nil - } - } - public static func parse_updateFavedStickers(_ reader: BufferReader) -> Update? { - return Api.Update.updateFavedStickers - } - public static func parse_updateFolderPeers(_ reader: BufferReader) -> Update? { - var _1: [Api.FolderPeer]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.FolderPeer.self) - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateFolderPeers(folderPeers: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateGeoLiveViewed(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateGeoLiveViewed(peer: _1!, msgId: _2!) - } - else { - return nil - } - } - public static func parse_updateGroupCall(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.GroupCall? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.GroupCall - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateGroupCall(chatId: _1!, call: _2!) - } - else { - return nil - } - } - public static func parse_updateGroupCallConnection(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.DataJSON? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateGroupCallConnection(flags: _1!, params: _2!) - } - else { - return nil - } - } - public static func parse_updateGroupCallParticipants(_ reader: BufferReader) -> Update? { - var _1: Api.InputGroupCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall - } - var _2: [Api.GroupCallParticipant]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) - } - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateGroupCallParticipants(call: _1!, participants: _2!, version: _3!) - } - else { - return nil - } - } - public static func parse_updateInlineBotCallbackQuery(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: Api.InputBotInlineMessageID? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID - } - var _5: Int64? - _5 = reader.readInt64() - var _6: Buffer? - if Int(_1!) & Int(1 << 0) != 0 {_6 = parseBytes(reader) } - var _7: String? - if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.Update.updateInlineBotCallbackQuery(flags: _1!, queryId: _2!, userId: _3!, msgId: _4!, chatInstance: _5!, data: _6, gameShortName: _7) - } - else { - return nil - } - } - public static func parse_updateLangPack(_ reader: BufferReader) -> Update? { - var _1: Api.LangPackDifference? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.LangPackDifference - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateLangPack(difference: _1!) - } - else { - return nil - } - } - public static func parse_updateLangPackTooLong(_ reader: BufferReader) -> Update? { + public static func parse_statsGraphAsync(_ reader: BufferReader) -> StatsGraph? { var _1: String? _1 = parseString(reader) let _c1 = _1 != nil if _c1 { - return Api.Update.updateLangPackTooLong(langCode: _1!) + return Api.StatsGraph.statsGraphAsync(token: _1!) } else { return nil } } - public static func parse_updateLoginToken(_ reader: BufferReader) -> Update? { - return Api.Update.updateLoginToken - } - public static func parse_updateMessageID(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateMessageID(id: _1!, randomId: _2!) - } - else { - return nil - } - } - public static func parse_updateMessagePoll(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Api.Poll? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Poll - } } - var _4: Api.PollResults? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.PollResults - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateMessagePoll(flags: _1!, pollId: _2!, poll: _3, results: _4!) - } - else { - return nil - } - } - public static func parse_updateMessagePollVote(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: [Buffer]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) - } - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateMessagePollVote(pollId: _1!, userId: _2!, options: _3!, qts: _4!) - } - else { - return nil - } - } - public static func parse_updateMessageReactions(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.MessageReactions? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.MessageReactions - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateMessageReactions(peer: _1!, msgId: _2!, reactions: _3!) - } - else { - return nil - } - } - public static func parse_updateNewChannelMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Message? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Message - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateNewChannelMessage(message: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateNewEncryptedMessage(_ reader: BufferReader) -> Update? { - var _1: Api.EncryptedMessage? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.EncryptedMessage - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateNewEncryptedMessage(message: _1!, qts: _2!) - } - else { - return nil - } - } - public static func parse_updateNewMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Message? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Message - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateNewMessage(message: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateNewScheduledMessage(_ reader: BufferReader) -> Update? { - var _1: Api.Message? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Message - } + public static func parse_statsGraphError(_ reader: BufferReader) -> StatsGraph? { + var _1: String? + _1 = parseString(reader) let _c1 = _1 != nil if _c1 { - return Api.Update.updateNewScheduledMessage(message: _1!) + return Api.StatsGraph.statsGraphError(error: _1!) } else { return nil } } - public static func parse_updateNewStickerSet(_ reader: BufferReader) -> Update? { - var _1: Api.messages.StickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateNewStickerSet(stickerset: _1!) - } - else { - return nil - } - } - public static func parse_updateNotifySettings(_ reader: BufferReader) -> Update? { - var _1: Api.NotifyPeer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.NotifyPeer - } - var _2: Api.PeerNotifySettings? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateNotifySettings(peer: _1!, notifySettings: _2!) - } - else { - return nil - } - } - public static func parse_updatePeerBlocked(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Api.Bool? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Bool - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updatePeerBlocked(peerId: _1!, blocked: _2!) - } - else { - return nil - } - } - public static func parse_updatePeerHistoryTTL(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.Peer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updatePeerHistoryTTL(flags: _1!, peer: _2!, ttlPeriod: _3) - } - else { - return nil - } - } - public static func parse_updatePeerLocated(_ reader: BufferReader) -> Update? { - var _1: [Api.PeerLocated]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerLocated.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updatePeerLocated(peers: _1!) - } - else { - return nil - } - } - public static func parse_updatePeerSettings(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Api.PeerSettings? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PeerSettings - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updatePeerSettings(peer: _1!, settings: _2!) - } - else { - return nil - } - } - public static func parse_updatePendingJoinRequests(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - var _3: [Int64]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updatePendingJoinRequests(peer: _1!, requestsPending: _2!, recentRequesters: _3!) - } - else { - return nil - } - } - public static func parse_updatePhoneCall(_ reader: BufferReader) -> Update? { - var _1: Api.PhoneCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updatePhoneCall(phoneCall: _1!) - } - else { - return nil - } - } - public static func parse_updatePhoneCallSignalingData(_ reader: BufferReader) -> Update? { + + } +} +public extension Api { + enum StatsGroupTopAdmin: TypeConstructorDescription { + case statsGroupTopAdmin(userId: Int64, deleted: Int32, kicked: Int32, banned: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGroupTopAdmin(let userId, let deleted, let kicked, let banned): + if boxed { + buffer.appendInt32(-682079097) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(deleted, buffer: buffer, boxed: false) + serializeInt32(kicked, buffer: buffer, boxed: false) + serializeInt32(banned, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGroupTopAdmin(let userId, let deleted, let kicked, let banned): + return ("statsGroupTopAdmin", [("userId", String(describing: userId)), ("deleted", String(describing: deleted)), ("kicked", String(describing: kicked)), ("banned", String(describing: banned))]) + } + } + + public static func parse_statsGroupTopAdmin(_ reader: BufferReader) -> StatsGroupTopAdmin? { var _1: Int64? _1 = reader.readInt64() - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updatePhoneCallSignalingData(phoneCallId: _1!, data: _2!) - } - else { - return nil - } - } - public static func parse_updatePinnedChannelMessages(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: [Int32]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Update.updatePinnedChannelMessages(flags: _1!, channelId: _2!, messages: _3!, pts: _4!, ptsCount: _5!) - } - else { - return nil - } - } - public static func parse_updatePinnedDialogs(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: [Api.DialogPeer]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogPeer.self) - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updatePinnedDialogs(flags: _1!, folderId: _2, order: _3) - } - else { - return nil - } - } - public static func parse_updatePinnedMessages(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.Peer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _3: [Int32]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Update.updatePinnedMessages(flags: _1!, peer: _2!, messages: _3!, pts: _4!, ptsCount: _5!) - } - else { - return nil - } - } - public static func parse_updatePrivacy(_ reader: BufferReader) -> Update? { - var _1: Api.PrivacyKey? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PrivacyKey - } - var _2: [Api.PrivacyRule]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updatePrivacy(key: _1!, rules: _2!) - } - else { - return nil - } - } - public static func parse_updatePtsChanged(_ reader: BufferReader) -> Update? { - return Api.Update.updatePtsChanged - } - public static func parse_updateReadChannelDiscussionInbox(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } - var _6: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Update.updateReadChannelDiscussionInbox(flags: _1!, channelId: _2!, topMsgId: _3!, readMaxId: _4!, broadcastId: _5, broadcastPost: _6) - } - else { - return nil - } - } - public static func parse_updateReadChannelDiscussionOutbox(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateReadChannelDiscussionOutbox(channelId: _1!, topMsgId: _2!, readMaxId: _3!) - } - else { - return nil - } - } - public static func parse_updateReadChannelInbox(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Int32? - _6 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Update.updateReadChannelInbox(flags: _1!, folderId: _2, channelId: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!) - } - else { - return nil - } - } - public static func parse_updateReadChannelOutbox(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateReadChannelOutbox(channelId: _1!, maxId: _2!) - } - else { - return nil - } - } - public static func parse_updateReadFeaturedStickers(_ reader: BufferReader) -> Update? { - return Api.Update.updateReadFeaturedStickers - } - public static func parse_updateReadHistoryInbox(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: Api.Peer? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Int32? - _6 = reader.readInt32() - var _7: Int32? - _7 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.Update.updateReadHistoryInbox(flags: _1!, folderId: _2, peer: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!, ptsCount: _7!) - } - else { - return nil - } - } - public static func parse_updateReadHistoryOutbox(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } var _2: Int32? _2 = reader.readInt32() var _3: Int32? @@ -3242,17 +673,82 @@ public extension Api { let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateReadHistoryOutbox(peer: _1!, maxId: _2!, pts: _3!, ptsCount: _4!) + return Api.StatsGroupTopAdmin.statsGroupTopAdmin(userId: _1!, deleted: _2!, kicked: _3!, banned: _4!) } else { return nil } } - public static func parse_updateReadMessagesContents(_ reader: BufferReader) -> Update? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + + } +} +public extension Api { + enum StatsGroupTopInviter: TypeConstructorDescription { + case statsGroupTopInviter(userId: Int64, invitations: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGroupTopInviter(let userId, let invitations): + if boxed { + buffer.appendInt32(1398765469) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(invitations, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGroupTopInviter(let userId, let invitations): + return ("statsGroupTopInviter", [("userId", String(describing: userId)), ("invitations", String(describing: invitations))]) + } + } + + public static func parse_statsGroupTopInviter(_ reader: BufferReader) -> StatsGroupTopInviter? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StatsGroupTopInviter.statsGroupTopInviter(userId: _1!, invitations: _2!) } + else { + return nil + } + } + + } +} +public extension Api { + enum StatsGroupTopPoster: TypeConstructorDescription { + case statsGroupTopPoster(userId: Int64, messages: Int32, avgChars: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGroupTopPoster(let userId, let messages, let avgChars): + if boxed { + buffer.appendInt32(-1660637285) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(messages, buffer: buffer, boxed: false) + serializeInt32(avgChars, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGroupTopPoster(let userId, let messages, let avgChars): + return ("statsGroupTopPoster", [("userId", String(describing: userId)), ("messages", String(describing: messages)), ("avgChars", String(describing: avgChars))]) + } + } + + public static func parse_statsGroupTopPoster(_ reader: BufferReader) -> StatsGroupTopPoster? { + var _1: Int64? + _1 = reader.readInt64() var _2: Int32? _2 = reader.readInt32() var _3: Int32? @@ -3261,57 +757,121 @@ public extension Api { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.Update.updateReadMessagesContents(messages: _1!, pts: _2!, ptsCount: _3!) + return Api.StatsGroupTopPoster.statsGroupTopPoster(userId: _1!, messages: _2!, avgChars: _3!) } else { return nil } } - public static func parse_updateRecentStickers(_ reader: BufferReader) -> Update? { - return Api.Update.updateRecentStickers - } - public static func parse_updateSavedGifs(_ reader: BufferReader) -> Update? { - return Api.Update.updateSavedGifs - } - public static func parse_updateSavedRingtones(_ reader: BufferReader) -> Update? { - return Api.Update.updateSavedRingtones - } - public static func parse_updateServiceNotification(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: Api.MessageMedia? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.MessageMedia - } - var _6: [Api.MessageEntity]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } + + } +} +public extension Api { + enum StatsPercentValue: TypeConstructorDescription { + case statsPercentValue(part: Double, total: Double) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsPercentValue(let part, let total): + if boxed { + buffer.appendInt32(-875679776) + } + serializeDouble(part, buffer: buffer, boxed: false) + serializeDouble(total, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsPercentValue(let part, let total): + return ("statsPercentValue", [("part", String(describing: part)), ("total", String(describing: total))]) + } + } + + public static func parse_statsPercentValue(_ reader: BufferReader) -> StatsPercentValue? { + var _1: Double? + _1 = reader.readDouble() + var _2: Double? + _2 = reader.readDouble() let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Update.updateServiceNotification(flags: _1!, inboxDate: _2, type: _3!, message: _4!, media: _5!, entities: _6!) + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StatsPercentValue.statsPercentValue(part: _1!, total: _2!) } else { return nil } } - public static func parse_updateStickerSets(_ reader: BufferReader) -> Update? { - return Api.Update.updateStickerSets + + } +} +public extension Api { + enum StatsURL: TypeConstructorDescription { + case statsURL(url: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsURL(let url): + if boxed { + buffer.appendInt32(1202287072) + } + serializeString(url, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsURL(let url): + return ("statsURL", [("url", String(describing: url))]) + } + } + + public static func parse_statsURL(_ reader: BufferReader) -> StatsURL? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.StatsURL.statsURL(url: _1!) + } + else { + return nil + } } - public static func parse_updateStickerSetsOrder(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() + + } +} +public extension Api { + enum StickerPack: TypeConstructorDescription { + case stickerPack(emoticon: String, documents: [Int64]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stickerPack(let emoticon, let documents): + if boxed { + buffer.appendInt32(313694676) + } + serializeString(emoticon, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents.count)) + for item in documents { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stickerPack(let emoticon, let documents): + return ("stickerPack", [("emoticon", String(describing: emoticon)), ("documents", String(describing: documents))]) + } + } + + public static func parse_stickerPack(_ reader: BufferReader) -> StickerPack? { + var _1: String? + _1 = parseString(reader) var _2: [Int64]? if let _ = reader.readInt32() { _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) @@ -3319,165 +879,7 @@ public extension Api { let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.Update.updateStickerSetsOrder(flags: _1!, order: _2!) - } - else { - return nil - } - } - public static func parse_updateTheme(_ reader: BufferReader) -> Update? { - var _1: Api.Theme? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Theme - } - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateTheme(theme: _1!) - } - else { - return nil - } - } - public static func parse_updateTranscribedAudio(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.Peer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _3: Int32? - _3 = reader.readInt32() - var _4: Int64? - _4 = reader.readInt64() - var _5: String? - _5 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Update.updateTranscribedAudio(flags: _1!, peer: _2!, msgId: _3!, transcriptionId: _4!, text: _5!) - } - else { - return nil - } - } - public static func parse_updateUserName(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateUserName(userId: _1!, firstName: _2!, lastName: _3!, username: _4!) - } - else { - return nil - } - } - public static func parse_updateUserPhone(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateUserPhone(userId: _1!, phone: _2!) - } - else { - return nil - } - } - public static func parse_updateUserPhoto(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.UserProfilePhoto? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto - } - var _4: Api.Bool? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Bool - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateUserPhoto(userId: _1!, date: _2!, photo: _3!, previous: _4!) - } - else { - return nil - } - } - public static func parse_updateUserStatus(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.UserStatus? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.UserStatus - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateUserStatus(userId: _1!, status: _2!) - } - else { - return nil - } - } - public static func parse_updateUserTyping(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Api.SendMessageAction? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.SendMessageAction - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateUserTyping(userId: _1!, action: _2!) - } - else { - return nil - } - } - public static func parse_updateWebPage(_ reader: BufferReader) -> Update? { - var _1: Api.WebPage? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.WebPage - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.Update.updateWebPage(webpage: _1!, pts: _2!, ptsCount: _3!) - } - else { - return nil - } - } - public static func parse_updateWebViewResultSent(_ reader: BufferReader) -> Update? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.Update.updateWebViewResultSent(queryId: _1!) + return Api.StickerPack.stickerPack(emoticon: _1!, documents: _2!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index 8a3362dbfb..b6b4d1684b 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -1,1035 +1,81 @@ public extension Api { - enum Updates: TypeConstructorDescription { - case updateShort(update: Api.Update, date: Int32) - case updateShortChatMessage(flags: Int32, id: Int32, fromId: Int64, chatId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) - case updateShortMessage(flags: Int32, id: Int32, userId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) - case updateShortSentMessage(flags: Int32, id: Int32, pts: Int32, ptsCount: Int32, date: Int32, media: Api.MessageMedia?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) - case updates(updates: [Api.Update], users: [Api.User], chats: [Api.Chat], date: Int32, seq: Int32) - case updatesCombined(updates: [Api.Update], users: [Api.User], chats: [Api.Chat], date: Int32, seqStart: Int32, seq: Int32) - case updatesTooLong + enum StickerSet: TypeConstructorDescription { + case stickerSet(flags: Int32, installedDate: Int32?, id: Int64, accessHash: Int64, title: String, shortName: String, thumbs: [Api.PhotoSize]?, thumbDcId: Int32?, thumbVersion: Int32?, thumbDocumentId: Int64?, count: Int32, hash: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .updateShort(let update, let date): + case .stickerSet(let flags, let installedDate, let id, let accessHash, let title, let shortName, let thumbs, let thumbDcId, let thumbVersion, let thumbDocumentId, let count, let hash): if boxed { - buffer.appendInt32(2027216577) - } - update.serialize(buffer, true) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .updateShortChatMessage(let flags, let id, let fromId, let chatId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): - if boxed { - buffer.appendInt32(1299050149) + buffer.appendInt32(768691932) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt64(fromId, buffer: buffer, boxed: false) - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} - if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(installedDate!, buffer: buffer, boxed: false)} + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(shortName, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(thumbs!.count)) + for item in thumbs! { item.serialize(buffer, true) }} - if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - case .updateShortMessage(let flags, let id, let userId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): - if boxed { - buffer.appendInt32(826001400) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} - if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - case .updateShortSentMessage(let flags, let id, let pts, let ptsCount, let date, let media, let entities, let ttlPeriod): - if boxed { - buffer.appendInt32(-1877614335) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 9) != 0 {media!.serialize(buffer, true)} - if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - break - case .updates(let updates, let users, let chats, let date, let seq): - if boxed { - buffer.appendInt32(1957577280) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(updates.count)) - for item in updates { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(seq, buffer: buffer, boxed: false) - break - case .updatesCombined(let updates, let users, let chats, let date, let seqStart, let seq): - if boxed { - buffer.appendInt32(1918567619) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(updates.count)) - for item in updates { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(seqStart, buffer: buffer, boxed: false) - serializeInt32(seq, buffer: buffer, boxed: false) - break - case .updatesTooLong: - if boxed { - buffer.appendInt32(-484987010) - } - + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(thumbDcId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(thumbVersion!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 8) != 0 {serializeInt64(thumbDocumentId!, buffer: buffer, boxed: false)} + serializeInt32(count, buffer: buffer, boxed: false) + serializeInt32(hash, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .updateShort(let update, let date): - return ("updateShort", [("update", String(describing: update)), ("date", String(describing: date))]) - case .updateShortChatMessage(let flags, let id, let fromId, let chatId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): - return ("updateShortChatMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("chatId", String(describing: chatId)), ("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) - case .updateShortMessage(let flags, let id, let userId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): - return ("updateShortMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) - case .updateShortSentMessage(let flags, let id, let pts, let ptsCount, let date, let media, let entities, let ttlPeriod): - return ("updateShortSentMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("media", String(describing: media)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) - case .updates(let updates, let users, let chats, let date, let seq): - return ("updates", [("updates", String(describing: updates)), ("users", String(describing: users)), ("chats", String(describing: chats)), ("date", String(describing: date)), ("seq", String(describing: seq))]) - case .updatesCombined(let updates, let users, let chats, let date, let seqStart, let seq): - return ("updatesCombined", [("updates", String(describing: updates)), ("users", String(describing: users)), ("chats", String(describing: chats)), ("date", String(describing: date)), ("seqStart", String(describing: seqStart)), ("seq", String(describing: seq))]) - case .updatesTooLong: - return ("updatesTooLong", []) + case .stickerSet(let flags, let installedDate, let id, let accessHash, let title, let shortName, let thumbs, let thumbDcId, let thumbVersion, let thumbDocumentId, let count, let hash): + return ("stickerSet", [("flags", String(describing: flags)), ("installedDate", String(describing: installedDate)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("title", String(describing: title)), ("shortName", String(describing: shortName)), ("thumbs", String(describing: thumbs)), ("thumbDcId", String(describing: thumbDcId)), ("thumbVersion", String(describing: thumbVersion)), ("thumbDocumentId", String(describing: thumbDocumentId)), ("count", String(describing: count)), ("hash", String(describing: hash))]) } } - public static func parse_updateShort(_ reader: BufferReader) -> Updates? { - var _1: Api.Update? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Update - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Updates.updateShort(update: _1!, date: _2!) - } - else { - return nil - } - } - public static func parse_updateShortChatMessage(_ reader: BufferReader) -> Updates? { + public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? - _2 = reader.readInt32() + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } var _3: Int64? _3 = reader.readInt64() var _4: Int64? _4 = reader.readInt64() var _5: String? _5 = parseString(reader) - var _6: Int32? - _6 = reader.readInt32() - var _7: Int32? - _7 = reader.readInt32() - var _8: Int32? - _8 = reader.readInt32() - var _9: Api.MessageFwdHeader? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader - } } - var _10: Int64? - if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt64() } - var _11: Api.MessageReplyHeader? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader - } } - var _12: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { - _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - var _13: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_13 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = (Int(_1!) & Int(1 << 2) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 3) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 25) == 0) || _13 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { - return Api.Updates.updateShortChatMessage(flags: _1!, id: _2!, fromId: _3!, chatId: _4!, message: _5!, pts: _6!, ptsCount: _7!, date: _8!, fwdFrom: _9, viaBotId: _10, replyTo: _11, entities: _12, ttlPeriod: _13) - } - else { - return nil - } - } - public static func parse_updateShortMessage(_ reader: BufferReader) -> Updates? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: Int32? - _5 = reader.readInt32() - var _6: Int32? - _6 = reader.readInt32() - var _7: Int32? - _7 = reader.readInt32() - var _8: Api.MessageFwdHeader? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader - } } - var _9: Int64? - if Int(_1!) & Int(1 << 11) != 0 {_9 = reader.readInt64() } - var _10: Api.MessageReplyHeader? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader - } } - var _11: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { - _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - var _12: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_12 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 11) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 3) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 25) == 0) || _12 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 { - return Api.Updates.updateShortMessage(flags: _1!, id: _2!, userId: _3!, message: _4!, pts: _5!, ptsCount: _6!, date: _7!, fwdFrom: _8, viaBotId: _9, replyTo: _10, entities: _11, ttlPeriod: _12) - } - else { - return nil - } - } - public static func parse_updateShortSentMessage(_ reader: BufferReader) -> Updates? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Api.MessageMedia? - if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.MessageMedia - } } - var _7: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - var _8: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_8 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 9) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 7) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 25) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.Updates.updateShortSentMessage(flags: _1!, id: _2!, pts: _3!, ptsCount: _4!, date: _5!, media: _6, entities: _7, ttlPeriod: _8) - } - else { - return nil - } - } - public static func parse_updates(_ reader: BufferReader) -> Updates? { - var _1: [Api.Update]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.Updates.updates(updates: _1!, users: _2!, chats: _3!, date: _4!, seq: _5!) - } - else { - return nil - } - } - public static func parse_updatesCombined(_ reader: BufferReader) -> Updates? { - var _1: [Api.Update]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Int32? - _6 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Updates.updatesCombined(updates: _1!, users: _2!, chats: _3!, date: _4!, seqStart: _5!, seq: _6!) - } - else { - return nil - } - } - public static func parse_updatesTooLong(_ reader: BufferReader) -> Updates? { - return Api.Updates.updatesTooLong - } - - } -} -public extension Api { - enum UrlAuthResult: TypeConstructorDescription { - case urlAuthResultAccepted(url: String) - case urlAuthResultDefault - case urlAuthResultRequest(flags: Int32, bot: Api.User, domain: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .urlAuthResultAccepted(let url): - if boxed { - buffer.appendInt32(-1886646706) - } - serializeString(url, buffer: buffer, boxed: false) - break - case .urlAuthResultDefault: - if boxed { - buffer.appendInt32(-1445536993) - } - - break - case .urlAuthResultRequest(let flags, let bot, let domain): - if boxed { - buffer.appendInt32(-1831650802) - } - serializeInt32(flags, buffer: buffer, boxed: false) - bot.serialize(buffer, true) - serializeString(domain, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .urlAuthResultAccepted(let url): - return ("urlAuthResultAccepted", [("url", String(describing: url))]) - case .urlAuthResultDefault: - return ("urlAuthResultDefault", []) - case .urlAuthResultRequest(let flags, let bot, let domain): - return ("urlAuthResultRequest", [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("domain", String(describing: domain))]) - } - } - - public static func parse_urlAuthResultAccepted(_ reader: BufferReader) -> UrlAuthResult? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.UrlAuthResult.urlAuthResultAccepted(url: _1!) - } - else { - return nil - } - } - public static func parse_urlAuthResultDefault(_ reader: BufferReader) -> UrlAuthResult? { - return Api.UrlAuthResult.urlAuthResultDefault - } - public static func parse_urlAuthResultRequest(_ reader: BufferReader) -> UrlAuthResult? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.User? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.User - } - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.UrlAuthResult.urlAuthResultRequest(flags: _1!, bot: _2!, domain: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum User: TypeConstructorDescription { - case user(flags: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?) - case userEmpty(id: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode): - if boxed { - buffer.appendInt32(1073147056) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt64(accessHash!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(firstName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(lastName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(username!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(phone!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 6) != 0 {status!.serialize(buffer, true)} - if Int(flags) & Int(1 << 14) != 0 {serializeInt32(botInfoVersion!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 18) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(restrictionReason!.count)) - for item in restrictionReason! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 19) != 0 {serializeString(botInlinePlaceholder!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 22) != 0 {serializeString(langCode!, buffer: buffer, boxed: false)} - break - case .userEmpty(let id): - if boxed { - buffer.appendInt32(-742634630) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode): - return ("user", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username)), ("phone", String(describing: phone)), ("photo", String(describing: photo)), ("status", String(describing: status)), ("botInfoVersion", String(describing: botInfoVersion)), ("restrictionReason", String(describing: restrictionReason)), ("botInlinePlaceholder", String(describing: botInlinePlaceholder)), ("langCode", String(describing: langCode))]) - case .userEmpty(let id): - return ("userEmpty", [("id", String(describing: id))]) - } - } - - public static func parse_user(_ reader: BufferReader) -> User? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt64() } - var _4: String? - if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } - var _5: String? - if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) } var _6: String? - if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } - var _7: String? - if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) } - var _8: Api.UserProfilePhoto? - if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto - } } - var _9: Api.UserStatus? - if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.UserStatus - } } - var _10: Int32? - if Int(_1!) & Int(1 << 14) != 0 {_10 = reader.readInt32() } - var _11: [Api.RestrictionReason]? - if Int(_1!) & Int(1 << 18) != 0 {if let _ = reader.readInt32() { - _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) - } } - var _12: String? - if Int(_1!) & Int(1 << 19) != 0 {_12 = parseString(reader) } - var _13: String? - if Int(_1!) & Int(1 << 22) != 0 {_13 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 18) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 19) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 22) == 0) || _13 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { - return Api.User.user(flags: _1!, id: _2!, accessHash: _3, firstName: _4, lastName: _5, username: _6, phone: _7, photo: _8, status: _9, botInfoVersion: _10, restrictionReason: _11, botInlinePlaceholder: _12, langCode: _13) - } - else { - return nil - } - } - public static func parse_userEmpty(_ reader: BufferReader) -> User? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.User.userEmpty(id: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum UserFull: TypeConstructorDescription { - case userFull(flags: Int32, id: Int64, about: String?, settings: Api.PeerSettings, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights): - if boxed { - buffer.appendInt32(-1938625919) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeString(about!, buffer: buffer, boxed: false)} - settings.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {profilePhoto!.serialize(buffer, true)} - notifySettings.serialize(buffer, true) - if Int(flags) & Int(1 << 3) != 0 {botInfo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} - serializeInt32(commonChatsCount, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 14) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 15) != 0 {serializeString(themeEmoticon!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 16) != 0 {serializeString(privateForwardName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 17) != 0 {botGroupAdminRights!.serialize(buffer, true)} - if Int(flags) & Int(1 << 18) != 0 {botBroadcastAdminRights!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights): - return ("userFull", [("flags", String(describing: flags)), ("id", String(describing: id)), ("about", String(describing: about)), ("settings", String(describing: settings)), ("profilePhoto", String(describing: profilePhoto)), ("notifySettings", String(describing: notifySettings)), ("botInfo", String(describing: botInfo)), ("pinnedMsgId", String(describing: pinnedMsgId)), ("commonChatsCount", String(describing: commonChatsCount)), ("folderId", String(describing: folderId)), ("ttlPeriod", String(describing: ttlPeriod)), ("themeEmoticon", String(describing: themeEmoticon)), ("privateForwardName", String(describing: privateForwardName)), ("botGroupAdminRights", String(describing: botGroupAdminRights)), ("botBroadcastAdminRights", String(describing: botBroadcastAdminRights))]) - } - } - - public static func parse_userFull(_ reader: BufferReader) -> UserFull? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: String? - if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } - var _4: Api.PeerSettings? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.PeerSettings - } - var _5: Api.Photo? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.Photo - } } - var _6: Api.PeerNotifySettings? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings - } - var _7: Api.BotInfo? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.BotInfo + _6 = parseString(reader) + var _7: [Api.PhotoSize]? + if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self) } } var _8: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_8 = reader.readInt32() } + if Int(_1!) & Int(1 << 4) != 0 {_8 = reader.readInt32() } var _9: Int32? - _9 = reader.readInt32() - var _10: Int32? - if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt32() } + if Int(_1!) & Int(1 << 4) != 0 {_9 = reader.readInt32() } + var _10: Int64? + if Int(_1!) & Int(1 << 8) != 0 {_10 = reader.readInt64() } var _11: Int32? - if Int(_1!) & Int(1 << 14) != 0 {_11 = reader.readInt32() } - var _12: String? - if Int(_1!) & Int(1 << 15) != 0 {_12 = parseString(reader) } - var _13: String? - if Int(_1!) & Int(1 << 16) != 0 {_13 = parseString(reader) } - var _14: Api.ChatAdminRights? - if Int(_1!) & Int(1 << 17) != 0 {if let signature = reader.readInt32() { - _14 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights - } } - var _15: Api.ChatAdminRights? - if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { - _15 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 6) == 0) || _8 != nil - let _c9 = _9 != nil - let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 14) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 15) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 16) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 17) == 0) || _14 != nil - let _c15 = (Int(_1!) & Int(1 << 18) == 0) || _15 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { - return Api.UserFull.userFull(flags: _1!, id: _2!, about: _3, settings: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!, folderId: _10, ttlPeriod: _11, themeEmoticon: _12, privateForwardName: _13, botGroupAdminRights: _14, botBroadcastAdminRights: _15) - } - else { - return nil - } - } - - } -} -public extension Api { - enum UserProfilePhoto: TypeConstructorDescription { - case userProfilePhoto(flags: Int32, photoId: Int64, strippedThumb: Buffer?, dcId: Int32) - case userProfilePhotoEmpty - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .userProfilePhoto(let flags, let photoId, let strippedThumb, let dcId): - if boxed { - buffer.appendInt32(-2100168954) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(photoId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeBytes(strippedThumb!, buffer: buffer, boxed: false)} - serializeInt32(dcId, buffer: buffer, boxed: false) - break - case .userProfilePhotoEmpty: - if boxed { - buffer.appendInt32(1326562017) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .userProfilePhoto(let flags, let photoId, let strippedThumb, let dcId): - return ("userProfilePhoto", [("flags", String(describing: flags)), ("photoId", String(describing: photoId)), ("strippedThumb", String(describing: strippedThumb)), ("dcId", String(describing: dcId))]) - case .userProfilePhotoEmpty: - return ("userProfilePhotoEmpty", []) - } - } - - public static func parse_userProfilePhoto(_ reader: BufferReader) -> UserProfilePhoto? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Buffer? - if Int(_1!) & Int(1 << 1) != 0 {_3 = parseBytes(reader) } - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.UserProfilePhoto.userProfilePhoto(flags: _1!, photoId: _2!, strippedThumb: _3, dcId: _4!) - } - else { - return nil - } - } - public static func parse_userProfilePhotoEmpty(_ reader: BufferReader) -> UserProfilePhoto? { - return Api.UserProfilePhoto.userProfilePhotoEmpty - } - - } -} -public extension Api { - enum UserStatus: TypeConstructorDescription { - case userStatusEmpty - case userStatusLastMonth - case userStatusLastWeek - case userStatusOffline(wasOnline: Int32) - case userStatusOnline(expires: Int32) - case userStatusRecently - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .userStatusEmpty: - if boxed { - buffer.appendInt32(164646985) - } - - break - case .userStatusLastMonth: - if boxed { - buffer.appendInt32(2011940674) - } - - break - case .userStatusLastWeek: - if boxed { - buffer.appendInt32(129960444) - } - - break - case .userStatusOffline(let wasOnline): - if boxed { - buffer.appendInt32(9203775) - } - serializeInt32(wasOnline, buffer: buffer, boxed: false) - break - case .userStatusOnline(let expires): - if boxed { - buffer.appendInt32(-306628279) - } - serializeInt32(expires, buffer: buffer, boxed: false) - break - case .userStatusRecently: - if boxed { - buffer.appendInt32(-496024847) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .userStatusEmpty: - return ("userStatusEmpty", []) - case .userStatusLastMonth: - return ("userStatusLastMonth", []) - case .userStatusLastWeek: - return ("userStatusLastWeek", []) - case .userStatusOffline(let wasOnline): - return ("userStatusOffline", [("wasOnline", String(describing: wasOnline))]) - case .userStatusOnline(let expires): - return ("userStatusOnline", [("expires", String(describing: expires))]) - case .userStatusRecently: - return ("userStatusRecently", []) - } - } - - public static func parse_userStatusEmpty(_ reader: BufferReader) -> UserStatus? { - return Api.UserStatus.userStatusEmpty - } - public static func parse_userStatusLastMonth(_ reader: BufferReader) -> UserStatus? { - return Api.UserStatus.userStatusLastMonth - } - public static func parse_userStatusLastWeek(_ reader: BufferReader) -> UserStatus? { - return Api.UserStatus.userStatusLastWeek - } - public static func parse_userStatusOffline(_ reader: BufferReader) -> UserStatus? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.UserStatus.userStatusOffline(wasOnline: _1!) - } - else { - return nil - } - } - public static func parse_userStatusOnline(_ reader: BufferReader) -> UserStatus? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.UserStatus.userStatusOnline(expires: _1!) - } - else { - return nil - } - } - public static func parse_userStatusRecently(_ reader: BufferReader) -> UserStatus? { - return Api.UserStatus.userStatusRecently - } - - } -} -public extension Api { - enum VideoSize: TypeConstructorDescription { - case videoSize(flags: Int32, type: String, w: Int32, h: Int32, size: Int32, videoStartTs: Double?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .videoSize(let flags, let type, let w, let h, let size, let videoStartTs): - if boxed { - buffer.appendInt32(-567037804) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(type, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) - serializeInt32(size, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .videoSize(let flags, let type, let w, let h, let size, let videoStartTs): - return ("videoSize", [("flags", String(describing: flags)), ("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("size", String(describing: size)), ("videoStartTs", String(describing: videoStartTs))]) - } - } - - public static func parse_videoSize(_ reader: BufferReader) -> VideoSize? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Double? - if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readDouble() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.VideoSize.videoSize(flags: _1!, type: _2!, w: _3!, h: _4!, size: _5!, videoStartTs: _6) - } - else { - return nil - } - } - - } -} -public extension Api { - enum WallPaper: TypeConstructorDescription { - case wallPaper(id: Int64, flags: Int32, accessHash: Int64, slug: String, document: Api.Document, settings: Api.WallPaperSettings?) - case wallPaperNoFile(id: Int64, flags: Int32, settings: Api.WallPaperSettings?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .wallPaper(let id, let flags, let accessHash, let slug, let document, let settings): - if boxed { - buffer.appendInt32(-1539849235) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeString(slug, buffer: buffer, boxed: false) - document.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {settings!.serialize(buffer, true)} - break - case .wallPaperNoFile(let id, let flags, let settings): - if boxed { - buffer.appendInt32(-528465642) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {settings!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .wallPaper(let id, let flags, let accessHash, let slug, let document, let settings): - return ("wallPaper", [("id", String(describing: id)), ("flags", String(describing: flags)), ("accessHash", String(describing: accessHash)), ("slug", String(describing: slug)), ("document", String(describing: document)), ("settings", String(describing: settings))]) - case .wallPaperNoFile(let id, let flags, let settings): - return ("wallPaperNoFile", [("id", String(describing: id)), ("flags", String(describing: flags)), ("settings", String(describing: settings))]) - } - } - - public static func parse_wallPaper(_ reader: BufferReader) -> WallPaper? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: Api.Document? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.Document - } - var _6: Api.WallPaperSettings? - if Int(_2!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_2!) & Int(1 << 2) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.WallPaper.wallPaper(id: _1!, flags: _2!, accessHash: _3!, slug: _4!, document: _5!, settings: _6) - } - else { - return nil - } - } - public static func parse_wallPaperNoFile(_ reader: BufferReader) -> WallPaper? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Api.WallPaperSettings? - if Int(_2!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_2!) & Int(1 << 2) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.WallPaper.wallPaperNoFile(id: _1!, flags: _2!, settings: _3) - } - else { - return nil - } - } - - } -} -public extension Api { - enum WallPaperSettings: TypeConstructorDescription { - case wallPaperSettings(flags: Int32, backgroundColor: Int32?, secondBackgroundColor: Int32?, thirdBackgroundColor: Int32?, fourthBackgroundColor: Int32?, intensity: Int32?, rotation: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .wallPaperSettings(let flags, let backgroundColor, let secondBackgroundColor, let thirdBackgroundColor, let fourthBackgroundColor, let intensity, let rotation): - if boxed { - buffer.appendInt32(499236004) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(backgroundColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(secondBackgroundColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {serializeInt32(thirdBackgroundColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(fourthBackgroundColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(intensity!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeInt32(rotation!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .wallPaperSettings(let flags, let backgroundColor, let secondBackgroundColor, let thirdBackgroundColor, let fourthBackgroundColor, let intensity, let rotation): - return ("wallPaperSettings", [("flags", String(describing: flags)), ("backgroundColor", String(describing: backgroundColor)), ("secondBackgroundColor", String(describing: secondBackgroundColor)), ("thirdBackgroundColor", String(describing: thirdBackgroundColor)), ("fourthBackgroundColor", String(describing: fourthBackgroundColor)), ("intensity", String(describing: intensity)), ("rotation", String(describing: rotation))]) - } - } - - public static func parse_wallPaperSettings(_ reader: BufferReader) -> WallPaperSettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_3 = reader.readInt32() } - var _4: Int32? - if Int(_1!) & Int(1 << 5) != 0 {_4 = reader.readInt32() } - var _5: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_5 = reader.readInt32() } - var _6: Int32? - if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() } - var _7: Int32? - if Int(_1!) & Int(1 << 4) != 0 {_7 = reader.readInt32() } + _11 = reader.readInt32() + var _12: Int32? + _12 = reader.readInt32() let _c1 = _1 != nil let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 4) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 5) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 6) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.WallPaperSettings.wallPaperSettings(flags: _1!, backgroundColor: _2, secondBackgroundColor: _3, thirdBackgroundColor: _4, fourthBackgroundColor: _5, intensity: _6, rotation: _7) + let _c8 = (Int(_1!) & Int(1 << 4) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 4) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil + let _c11 = _11 != nil + let _c12 = _12 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 { + return Api.StickerSet.stickerSet(flags: _1!, installedDate: _2, id: _3!, accessHash: _4!, title: _5!, shortName: _6!, thumbs: _7, thumbDcId: _8, thumbVersion: _9, thumbDocumentId: _10, count: _11!, hash: _12!) } else { return nil @@ -1039,289 +85,2034 @@ public extension Api { } } public extension Api { - enum WebAuthorization: TypeConstructorDescription { - case webAuthorization(hash: Int64, botId: Int64, domain: String, browser: String, platform: String, dateCreated: Int32, dateActive: Int32, ip: String, region: String) + enum StickerSetCovered: TypeConstructorDescription { + case stickerSetCovered(set: Api.StickerSet, cover: Api.Document) + case stickerSetFullCovered(set: Api.StickerSet, packs: [Api.StickerPack], documents: [Api.Document]) + case stickerSetMultiCovered(set: Api.StickerSet, covers: [Api.Document]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .webAuthorization(let hash, let botId, let domain, let browser, let platform, let dateCreated, let dateActive, let ip, let region): + case .stickerSetCovered(let set, let cover): if boxed { - buffer.appendInt32(-1493633966) + buffer.appendInt32(1678812626) + } + set.serialize(buffer, true) + cover.serialize(buffer, true) + break + case .stickerSetFullCovered(let set, let packs, let documents): + if boxed { + buffer.appendInt32(451763941) + } + set.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(packs.count)) + for item in packs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents.count)) + for item in documents { + item.serialize(buffer, true) + } + break + case .stickerSetMultiCovered(let set, let covers): + if boxed { + buffer.appendInt32(872932635) + } + set.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(covers.count)) + for item in covers { + item.serialize(buffer, true) } - serializeInt64(hash, buffer: buffer, boxed: false) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeString(domain, buffer: buffer, boxed: false) - serializeString(browser, buffer: buffer, boxed: false) - serializeString(platform, buffer: buffer, boxed: false) - serializeInt32(dateCreated, buffer: buffer, boxed: false) - serializeInt32(dateActive, buffer: buffer, boxed: false) - serializeString(ip, buffer: buffer, boxed: false) - serializeString(region, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .webAuthorization(let hash, let botId, let domain, let browser, let platform, let dateCreated, let dateActive, let ip, let region): - return ("webAuthorization", [("hash", String(describing: hash)), ("botId", String(describing: botId)), ("domain", String(describing: domain)), ("browser", String(describing: browser)), ("platform", String(describing: platform)), ("dateCreated", String(describing: dateCreated)), ("dateActive", String(describing: dateActive)), ("ip", String(describing: ip)), ("region", String(describing: region))]) + case .stickerSetCovered(let set, let cover): + return ("stickerSetCovered", [("set", String(describing: set)), ("cover", String(describing: cover))]) + case .stickerSetFullCovered(let set, let packs, let documents): + return ("stickerSetFullCovered", [("set", String(describing: set)), ("packs", String(describing: packs)), ("documents", String(describing: documents))]) + case .stickerSetMultiCovered(let set, let covers): + return ("stickerSetMultiCovered", [("set", String(describing: set)), ("covers", String(describing: covers))]) } } - public static func parse_webAuthorization(_ reader: BufferReader) -> WebAuthorization? { - var _1: Int64? - _1 = reader.readInt64() + public static func parse_stickerSetCovered(_ reader: BufferReader) -> StickerSetCovered? { + var _1: Api.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StickerSet + } + var _2: Api.Document? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Document + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StickerSetCovered.stickerSetCovered(set: _1!, cover: _2!) + } + else { + return nil + } + } + public static func parse_stickerSetFullCovered(_ reader: BufferReader) -> StickerSetCovered? { + var _1: Api.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StickerSet + } + var _2: [Api.StickerPack]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + } + var _3: [Api.Document]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.StickerSetCovered.stickerSetFullCovered(set: _1!, packs: _2!, documents: _3!) + } + else { + return nil + } + } + public static func parse_stickerSetMultiCovered(_ reader: BufferReader) -> StickerSetCovered? { + var _1: Api.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StickerSet + } + var _2: [Api.Document]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.StickerSetCovered.stickerSetMultiCovered(set: _1!, covers: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum Theme: TypeConstructorDescription { + case theme(flags: Int32, id: Int64, accessHash: Int64, slug: String, title: String, document: Api.Document?, settings: [Api.ThemeSettings]?, emoticon: String?, installsCount: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .theme(let flags, let id, let accessHash, let slug, let title, let document, let settings, let emoticon, let installsCount): + if boxed { + buffer.appendInt32(-1609668650) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeString(slug, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(settings!.count)) + for item in settings! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 6) != 0 {serializeString(emoticon!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(installsCount!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .theme(let flags, let id, let accessHash, let slug, let title, let document, let settings, let emoticon, let installsCount): + return ("theme", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings)), ("emoticon", String(describing: emoticon)), ("installsCount", String(describing: installsCount))]) + } + } + + public static func parse_theme(_ reader: BufferReader) -> Theme? { + var _1: Int32? + _1 = reader.readInt32() var _2: Int64? _2 = reader.readInt64() - var _3: String? - _3 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() var _4: String? _4 = parseString(reader) var _5: String? _5 = parseString(reader) - var _6: Int32? - _6 = reader.readInt32() - var _7: Int32? - _7 = reader.readInt32() + var _6: Api.Document? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.Document + } } + var _7: [Api.ThemeSettings]? + if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ThemeSettings.self) + } } var _8: String? - _8 = parseString(reader) - var _9: String? - _9 = parseString(reader) + if Int(_1!) & Int(1 << 6) != 0 {_8 = parseString(reader) } + var _9: Int32? + if Int(_1!) & Int(1 << 4) != 0 {_9 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 6) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 4) == 0) || _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.Theme.theme(flags: _1!, id: _2!, accessHash: _3!, slug: _4!, title: _5!, document: _6, settings: _7, emoticon: _8, installsCount: _9) + } + else { + return nil + } + } + + } +} +public extension Api { + enum ThemeSettings: TypeConstructorDescription { + case themeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.WallPaper?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .themeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper): + if boxed { + buffer.appendInt32(-94849324) + } + serializeInt32(flags, buffer: buffer, boxed: false) + baseTheme.serialize(buffer, true) + serializeInt32(accentColor, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messageColors!.count)) + for item in messageColors! { + serializeInt32(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .themeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper): + return ("themeSettings", [("flags", String(describing: flags)), ("baseTheme", String(describing: baseTheme)), ("accentColor", String(describing: accentColor)), ("outboxAccentColor", String(describing: outboxAccentColor)), ("messageColors", String(describing: messageColors)), ("wallpaper", String(describing: wallpaper))]) + } + } + + public static func parse_themeSettings(_ reader: BufferReader) -> ThemeSettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.BaseTheme? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.BaseTheme + } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() } + var _5: [Int32]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } } + var _6: Api.WallPaper? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.WallPaper + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.ThemeSettings.themeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum TopPeer: TypeConstructorDescription { + case topPeer(peer: Api.Peer, rating: Double) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .topPeer(let peer, let rating): + if boxed { + buffer.appendInt32(-305282981) + } + peer.serialize(buffer, true) + serializeDouble(rating, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .topPeer(let peer, let rating): + return ("topPeer", [("peer", String(describing: peer)), ("rating", String(describing: rating))]) + } + } + + public static func parse_topPeer(_ reader: BufferReader) -> TopPeer? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Double? + _2 = reader.readDouble() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.TopPeer.topPeer(peer: _1!, rating: _2!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum TopPeerCategory: TypeConstructorDescription { + case topPeerCategoryBotsInline + case topPeerCategoryBotsPM + case topPeerCategoryChannels + case topPeerCategoryCorrespondents + case topPeerCategoryForwardChats + case topPeerCategoryForwardUsers + case topPeerCategoryGroups + case topPeerCategoryPhoneCalls + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .topPeerCategoryBotsInline: + if boxed { + buffer.appendInt32(344356834) + } + + break + case .topPeerCategoryBotsPM: + if boxed { + buffer.appendInt32(-1419371685) + } + + break + case .topPeerCategoryChannels: + if boxed { + buffer.appendInt32(371037736) + } + + break + case .topPeerCategoryCorrespondents: + if boxed { + buffer.appendInt32(104314861) + } + + break + case .topPeerCategoryForwardChats: + if boxed { + buffer.appendInt32(-68239120) + } + + break + case .topPeerCategoryForwardUsers: + if boxed { + buffer.appendInt32(-1472172887) + } + + break + case .topPeerCategoryGroups: + if boxed { + buffer.appendInt32(-1122524854) + } + + break + case .topPeerCategoryPhoneCalls: + if boxed { + buffer.appendInt32(511092620) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .topPeerCategoryBotsInline: + return ("topPeerCategoryBotsInline", []) + case .topPeerCategoryBotsPM: + return ("topPeerCategoryBotsPM", []) + case .topPeerCategoryChannels: + return ("topPeerCategoryChannels", []) + case .topPeerCategoryCorrespondents: + return ("topPeerCategoryCorrespondents", []) + case .topPeerCategoryForwardChats: + return ("topPeerCategoryForwardChats", []) + case .topPeerCategoryForwardUsers: + return ("topPeerCategoryForwardUsers", []) + case .topPeerCategoryGroups: + return ("topPeerCategoryGroups", []) + case .topPeerCategoryPhoneCalls: + return ("topPeerCategoryPhoneCalls", []) + } + } + + public static func parse_topPeerCategoryBotsInline(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryBotsInline + } + public static func parse_topPeerCategoryBotsPM(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryBotsPM + } + public static func parse_topPeerCategoryChannels(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryChannels + } + public static func parse_topPeerCategoryCorrespondents(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryCorrespondents + } + public static func parse_topPeerCategoryForwardChats(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryForwardChats + } + public static func parse_topPeerCategoryForwardUsers(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryForwardUsers + } + public static func parse_topPeerCategoryGroups(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryGroups + } + public static func parse_topPeerCategoryPhoneCalls(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryPhoneCalls + } + + } +} +public extension Api { + enum TopPeerCategoryPeers: TypeConstructorDescription { + case topPeerCategoryPeers(category: Api.TopPeerCategory, count: Int32, peers: [Api.TopPeer]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .topPeerCategoryPeers(let category, let count, let peers): + if boxed { + buffer.appendInt32(-75283823) + } + category.serialize(buffer, true) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .topPeerCategoryPeers(let category, let count, let peers): + return ("topPeerCategoryPeers", [("category", String(describing: category)), ("count", String(describing: count)), ("peers", String(describing: peers))]) + } + } + + public static func parse_topPeerCategoryPeers(_ reader: BufferReader) -> TopPeerCategoryPeers? { + var _1: Api.TopPeerCategory? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.TopPeerCategory + } + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.TopPeer]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.TopPeer.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.TopPeerCategoryPeers.topPeerCategoryPeers(category: _1!, count: _2!, peers: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum Update: TypeConstructorDescription { + case updateAttachMenuBots + case updateBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, peer: Api.Peer, msgId: Int32, chatInstance: Int64, data: Buffer?, gameShortName: String?) + case updateBotChatInviteRequester(peer: Api.Peer, date: Int32, userId: Int64, about: String, invite: Api.ExportedChatInvite, qts: Int32) + case updateBotCommands(peer: Api.Peer, botId: Int64, commands: [Api.BotCommand]) + case updateBotInlineQuery(flags: Int32, queryId: Int64, userId: Int64, query: String, geo: Api.GeoPoint?, peerType: Api.InlineQueryPeerType?, offset: String) + case updateBotInlineSend(flags: Int32, userId: Int64, query: String, geo: Api.GeoPoint?, id: String, msgId: Api.InputBotInlineMessageID?) + case updateBotMenuButton(botId: Int64, button: Api.BotMenuButton) + case updateBotPrecheckoutQuery(flags: Int32, queryId: Int64, userId: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, currency: String, totalAmount: Int64) + case updateBotShippingQuery(queryId: Int64, userId: Int64, payload: Buffer, shippingAddress: Api.PostAddress) + case updateBotStopped(userId: Int64, date: Int32, stopped: Api.Bool, qts: Int32) + case updateBotWebhookJSON(data: Api.DataJSON) + case updateBotWebhookJSONQuery(queryId: Int64, data: Api.DataJSON, timeout: Int32) + case updateChannel(channelId: Int64) + case updateChannelAvailableMessages(channelId: Int64, availableMinId: Int32) + case updateChannelMessageForwards(channelId: Int64, id: Int32, forwards: Int32) + case updateChannelMessageViews(channelId: Int64, id: Int32, views: Int32) + case updateChannelParticipant(flags: Int32, channelId: Int64, date: Int32, actorId: Int64, userId: Int64, prevParticipant: Api.ChannelParticipant?, newParticipant: Api.ChannelParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) + case updateChannelReadMessagesContents(channelId: Int64, messages: [Int32]) + case updateChannelTooLong(flags: Int32, channelId: Int64, pts: Int32?) + case updateChannelUserTyping(flags: Int32, channelId: Int64, topMsgId: Int32?, fromId: Api.Peer, action: Api.SendMessageAction) + case updateChannelWebPage(channelId: Int64, webpage: Api.WebPage, pts: Int32, ptsCount: Int32) + case updateChat(chatId: Int64) + case updateChatDefaultBannedRights(peer: Api.Peer, defaultBannedRights: Api.ChatBannedRights, version: Int32) + case updateChatParticipant(flags: Int32, chatId: Int64, date: Int32, actorId: Int64, userId: Int64, prevParticipant: Api.ChatParticipant?, newParticipant: Api.ChatParticipant?, invite: Api.ExportedChatInvite?, qts: Int32) + case updateChatParticipantAdd(chatId: Int64, userId: Int64, inviterId: Int64, date: Int32, version: Int32) + case updateChatParticipantAdmin(chatId: Int64, userId: Int64, isAdmin: Api.Bool, version: Int32) + case updateChatParticipantDelete(chatId: Int64, userId: Int64, version: Int32) + case updateChatParticipants(participants: Api.ChatParticipants) + case updateChatUserTyping(chatId: Int64, fromId: Api.Peer, action: Api.SendMessageAction) + case updateConfig + case updateContactsReset + case updateDcOptions(dcOptions: [Api.DcOption]) + case updateDeleteChannelMessages(channelId: Int64, messages: [Int32], pts: Int32, ptsCount: Int32) + case updateDeleteMessages(messages: [Int32], pts: Int32, ptsCount: Int32) + case updateDeleteScheduledMessages(peer: Api.Peer, messages: [Int32]) + case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) + case updateDialogFilterOrder(order: [Int32]) + case updateDialogFilters + case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer) + case updateDialogUnreadMark(flags: Int32, peer: Api.DialogPeer) + case updateDraftMessage(peer: Api.Peer, draft: Api.DraftMessage) + case updateEditChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) + case updateEditMessage(message: Api.Message, pts: Int32, ptsCount: Int32) + case updateEncryptedChatTyping(chatId: Int32) + case updateEncryptedMessagesRead(chatId: Int32, maxDate: Int32, date: Int32) + case updateEncryption(chat: Api.EncryptedChat, date: Int32) + case updateFavedStickers + case updateFolderPeers(folderPeers: [Api.FolderPeer], pts: Int32, ptsCount: Int32) + case updateGeoLiveViewed(peer: Api.Peer, msgId: Int32) + case updateGroupCall(chatId: Int64, call: Api.GroupCall) + case updateGroupCallConnection(flags: Int32, params: Api.DataJSON) + case updateGroupCallParticipants(call: Api.InputGroupCall, participants: [Api.GroupCallParticipant], version: Int32) + case updateInlineBotCallbackQuery(flags: Int32, queryId: Int64, userId: Int64, msgId: Api.InputBotInlineMessageID, chatInstance: Int64, data: Buffer?, gameShortName: String?) + case updateLangPack(difference: Api.LangPackDifference) + case updateLangPackTooLong(langCode: String) + case updateLoginToken + case updateMessageID(id: Int32, randomId: Int64) + case updateMessagePoll(flags: Int32, pollId: Int64, poll: Api.Poll?, results: Api.PollResults) + case updateMessagePollVote(pollId: Int64, userId: Int64, options: [Buffer], qts: Int32) + case updateMessageReactions(peer: Api.Peer, msgId: Int32, reactions: Api.MessageReactions) + case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) + case updateNewEncryptedMessage(message: Api.EncryptedMessage, qts: Int32) + case updateNewMessage(message: Api.Message, pts: Int32, ptsCount: Int32) + case updateNewScheduledMessage(message: Api.Message) + case updateNewStickerSet(stickerset: Api.messages.StickerSet) + case updateNotifySettings(peer: Api.NotifyPeer, notifySettings: Api.PeerNotifySettings) + case updatePeerBlocked(peerId: Api.Peer, blocked: Api.Bool) + case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?) + case updatePeerLocated(peers: [Api.PeerLocated]) + case updatePeerSettings(peer: Api.Peer, settings: Api.PeerSettings) + case updatePendingJoinRequests(peer: Api.Peer, requestsPending: Int32, recentRequesters: [Int64]) + case updatePhoneCall(phoneCall: Api.PhoneCall) + case updatePhoneCallSignalingData(phoneCallId: Int64, data: Buffer) + case updatePinnedChannelMessages(flags: Int32, channelId: Int64, messages: [Int32], pts: Int32, ptsCount: Int32) + case updatePinnedDialogs(flags: Int32, folderId: Int32?, order: [Api.DialogPeer]?) + case updatePinnedMessages(flags: Int32, peer: Api.Peer, messages: [Int32], pts: Int32, ptsCount: Int32) + case updatePrivacy(key: Api.PrivacyKey, rules: [Api.PrivacyRule]) + case updatePtsChanged + case updateReadChannelDiscussionInbox(flags: Int32, channelId: Int64, topMsgId: Int32, readMaxId: Int32, broadcastId: Int64?, broadcastPost: Int32?) + case updateReadChannelDiscussionOutbox(channelId: Int64, topMsgId: Int32, readMaxId: Int32) + case updateReadChannelInbox(flags: Int32, folderId: Int32?, channelId: Int64, maxId: Int32, stillUnreadCount: Int32, pts: Int32) + case updateReadChannelOutbox(channelId: Int64, maxId: Int32) + case updateReadFeaturedEmojiStickers + case updateReadFeaturedStickers + case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32) + case updateReadHistoryOutbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32) + case updateReadMessagesContents(messages: [Int32], pts: Int32, ptsCount: Int32) + case updateRecentStickers + case updateSavedGifs + case updateSavedRingtones + case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity]) + case updateStickerSets + case updateStickerSetsOrder(flags: Int32, order: [Int64]) + case updateTheme(theme: Api.Theme) + case updateTranscribedAudio(flags: Int32, peer: Api.Peer, msgId: Int32, transcriptionId: Int64, text: String) + case updateUserName(userId: Int64, firstName: String, lastName: String, username: String) + case updateUserPhone(userId: Int64, phone: String) + case updateUserPhoto(userId: Int64, date: Int32, photo: Api.UserProfilePhoto, previous: Api.Bool) + case updateUserStatus(userId: Int64, status: Api.UserStatus) + case updateUserTyping(userId: Int64, action: Api.SendMessageAction) + case updateWebPage(webpage: Api.WebPage, pts: Int32, ptsCount: Int32) + case updateWebViewResultSent(queryId: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .updateAttachMenuBots: + if boxed { + buffer.appendInt32(397910539) + } + + break + case .updateBotCallbackQuery(let flags, let queryId, let userId, let peer, let msgId, let chatInstance, let data, let gameShortName): + if boxed { + buffer.appendInt32(-1177566067) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt64(chatInstance, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(gameShortName!, buffer: buffer, boxed: false)} + break + case .updateBotChatInviteRequester(let peer, let date, let userId, let about, let invite, let qts): + if boxed { + buffer.appendInt32(299870598) + } + peer.serialize(buffer, true) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(about, buffer: buffer, boxed: false) + invite.serialize(buffer, true) + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateBotCommands(let peer, let botId, let commands): + if boxed { + buffer.appendInt32(1299263278) + } + peer.serialize(buffer, true) + serializeInt64(botId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(commands.count)) + for item in commands { + item.serialize(buffer, true) + } + break + case .updateBotInlineQuery(let flags, let queryId, let userId, let query, let geo, let peerType, let offset): + if boxed { + buffer.appendInt32(1232025500) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(query, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {geo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {peerType!.serialize(buffer, true)} + serializeString(offset, buffer: buffer, boxed: false) + break + case .updateBotInlineSend(let flags, let userId, let query, let geo, let id, let msgId): + if boxed { + buffer.appendInt32(317794823) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(query, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {geo!.serialize(buffer, true)} + serializeString(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {msgId!.serialize(buffer, true)} + break + case .updateBotMenuButton(let botId, let button): + if boxed { + buffer.appendInt32(347625491) + } + serializeInt64(botId, buffer: buffer, boxed: false) + button.serialize(buffer, true) + break + case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount): + if boxed { + buffer.appendInt32(-1934976362) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeBytes(payload, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(totalAmount, buffer: buffer, boxed: false) + break + case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): + if boxed { + buffer.appendInt32(-1246823043) + } + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeBytes(payload, buffer: buffer, boxed: false) + shippingAddress.serialize(buffer, true) + break + case .updateBotStopped(let userId, let date, let stopped, let qts): + if boxed { + buffer.appendInt32(-997782967) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + stopped.serialize(buffer, true) + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateBotWebhookJSON(let data): + if boxed { + buffer.appendInt32(-2095595325) + } + data.serialize(buffer, true) + break + case .updateBotWebhookJSONQuery(let queryId, let data, let timeout): + if boxed { + buffer.appendInt32(-1684914010) + } + serializeInt64(queryId, buffer: buffer, boxed: false) + data.serialize(buffer, true) + serializeInt32(timeout, buffer: buffer, boxed: false) + break + case .updateChannel(let channelId): + if boxed { + buffer.appendInt32(1666927625) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + break + case .updateChannelAvailableMessages(let channelId, let availableMinId): + if boxed { + buffer.appendInt32(-1304443240) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(availableMinId, buffer: buffer, boxed: false) + break + case .updateChannelMessageForwards(let channelId, let id, let forwards): + if boxed { + buffer.appendInt32(-761649164) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt32(forwards, buffer: buffer, boxed: false) + break + case .updateChannelMessageViews(let channelId, let id, let views): + if boxed { + buffer.appendInt32(-232346616) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt32(views, buffer: buffer, boxed: false) + break + case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): + if boxed { + buffer.appendInt32(-1738720581) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(actorId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)} + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateChannelReadMessagesContents(let channelId, let messages): + if boxed { + buffer.appendInt32(1153291573) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + case .updateChannelTooLong(let flags, let channelId, let pts): + if boxed { + buffer.appendInt32(277713951) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(channelId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(pts!, buffer: buffer, boxed: false)} + break + case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let fromId, let action): + if boxed { + buffer.appendInt32(-1937192669) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(channelId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} + fromId.serialize(buffer, true) + action.serialize(buffer, true) + break + case .updateChannelWebPage(let channelId, let webpage, let pts, let ptsCount): + if boxed { + buffer.appendInt32(791390623) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + webpage.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateChat(let chatId): + if boxed { + buffer.appendInt32(-124097970) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + break + case .updateChatDefaultBannedRights(let peer, let defaultBannedRights, let version): + if boxed { + buffer.appendInt32(1421875280) + } + peer.serialize(buffer, true) + defaultBannedRights.serialize(buffer, true) + serializeInt32(version, buffer: buffer, boxed: false) + break + case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): + if boxed { + buffer.appendInt32(-796432838) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(actorId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {prevParticipant!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {newParticipant!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {invite!.serialize(buffer, true)} + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateChatParticipantAdd(let chatId, let userId, let inviterId, let date, let version): + if boxed { + buffer.appendInt32(1037718609) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt64(inviterId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(version, buffer: buffer, boxed: false) + break + case .updateChatParticipantAdmin(let chatId, let userId, let isAdmin, let version): + if boxed { + buffer.appendInt32(-674602590) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + isAdmin.serialize(buffer, true) + serializeInt32(version, buffer: buffer, boxed: false) + break + case .updateChatParticipantDelete(let chatId, let userId, let version): + if boxed { + buffer.appendInt32(-483443337) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(version, buffer: buffer, boxed: false) + break + case .updateChatParticipants(let participants): + if boxed { + buffer.appendInt32(125178264) + } + participants.serialize(buffer, true) + break + case .updateChatUserTyping(let chatId, let fromId, let action): + if boxed { + buffer.appendInt32(-2092401936) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + fromId.serialize(buffer, true) + action.serialize(buffer, true) + break + case .updateConfig: + if boxed { + buffer.appendInt32(-1574314746) + } + + break + case .updateContactsReset: + if boxed { + buffer.appendInt32(1887741886) + } + + break + case .updateDcOptions(let dcOptions): + if boxed { + buffer.appendInt32(-1906403213) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dcOptions.count)) + for item in dcOptions { + item.serialize(buffer, true) + } + break + case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-1020437742) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateDeleteMessages(let messages, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-1576161051) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateDeleteScheduledMessages(let peer, let messages): + if boxed { + buffer.appendInt32(-1870238482) + } + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + case .updateDialogFilter(let flags, let id, let filter): + if boxed { + buffer.appendInt32(654302845) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} + break + case .updateDialogFilterOrder(let order): + if boxed { + buffer.appendInt32(-1512627963) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + case .updateDialogFilters: + if boxed { + buffer.appendInt32(889491791) + } + + break + case .updateDialogPinned(let flags, let folderId, let peer): + if boxed { + buffer.appendInt32(1852826908) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + peer.serialize(buffer, true) + break + case .updateDialogUnreadMark(let flags, let peer): + if boxed { + buffer.appendInt32(-513517117) + } + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + break + case .updateDraftMessage(let peer, let draft): + if boxed { + buffer.appendInt32(-299124375) + } + peer.serialize(buffer, true) + draft.serialize(buffer, true) + break + case .updateEditChannelMessage(let message, let pts, let ptsCount): + if boxed { + buffer.appendInt32(457133559) + } + message.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateEditMessage(let message, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-469536605) + } + message.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateEncryptedChatTyping(let chatId): + if boxed { + buffer.appendInt32(386986326) + } + serializeInt32(chatId, buffer: buffer, boxed: false) + break + case .updateEncryptedMessagesRead(let chatId, let maxDate, let date): + if boxed { + buffer.appendInt32(956179895) + } + serializeInt32(chatId, buffer: buffer, boxed: false) + serializeInt32(maxDate, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .updateEncryption(let chat, let date): + if boxed { + buffer.appendInt32(-1264392051) + } + chat.serialize(buffer, true) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .updateFavedStickers: + if boxed { + buffer.appendInt32(-451831443) + } + + break + case .updateFolderPeers(let folderPeers, let pts, let ptsCount): + if boxed { + buffer.appendInt32(422972864) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(folderPeers.count)) + for item in folderPeers { + item.serialize(buffer, true) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateGeoLiveViewed(let peer, let msgId): + if boxed { + buffer.appendInt32(-2027964103) + } + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + break + case .updateGroupCall(let chatId, let call): + if boxed { + buffer.appendInt32(347227392) + } + serializeInt64(chatId, buffer: buffer, boxed: false) + call.serialize(buffer, true) + break + case .updateGroupCallConnection(let flags, let params): + if boxed { + buffer.appendInt32(192428418) + } + serializeInt32(flags, buffer: buffer, boxed: false) + params.serialize(buffer, true) + break + case .updateGroupCallParticipants(let call, let participants, let version): + if boxed { + buffer.appendInt32(-219423922) + } + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(participants.count)) + for item in participants { + item.serialize(buffer, true) + } + serializeInt32(version, buffer: buffer, boxed: false) + break + case .updateInlineBotCallbackQuery(let flags, let queryId, let userId, let msgId, let chatInstance, let data, let gameShortName): + if boxed { + buffer.appendInt32(1763610706) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + msgId.serialize(buffer, true) + serializeInt64(chatInstance, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(gameShortName!, buffer: buffer, boxed: false)} + break + case .updateLangPack(let difference): + if boxed { + buffer.appendInt32(1442983757) + } + difference.serialize(buffer, true) + break + case .updateLangPackTooLong(let langCode): + if boxed { + buffer.appendInt32(1180041828) + } + serializeString(langCode, buffer: buffer, boxed: false) + break + case .updateLoginToken: + if boxed { + buffer.appendInt32(1448076945) + } + + break + case .updateMessageID(let id, let randomId): + if boxed { + buffer.appendInt32(1318109142) + } + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt64(randomId, buffer: buffer, boxed: false) + break + case .updateMessagePoll(let flags, let pollId, let poll, let results): + if boxed { + buffer.appendInt32(-1398708869) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(pollId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {poll!.serialize(buffer, true)} + results.serialize(buffer, true) + break + case .updateMessagePollVote(let pollId, let userId, let options, let qts): + if boxed { + buffer.appendInt32(274961865) + } + serializeInt64(pollId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(options.count)) + for item in options { + serializeBytes(item, buffer: buffer, boxed: false) + } + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateMessageReactions(let peer, let msgId, let reactions): + if boxed { + buffer.appendInt32(357013699) + } + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + reactions.serialize(buffer, true) + break + case .updateNewChannelMessage(let message, let pts, let ptsCount): + if boxed { + buffer.appendInt32(1656358105) + } + message.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateNewEncryptedMessage(let message, let qts): + if boxed { + buffer.appendInt32(314359194) + } + message.serialize(buffer, true) + serializeInt32(qts, buffer: buffer, boxed: false) + break + case .updateNewMessage(let message, let pts, let ptsCount): + if boxed { + buffer.appendInt32(522914557) + } + message.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateNewScheduledMessage(let message): + if boxed { + buffer.appendInt32(967122427) + } + message.serialize(buffer, true) + break + case .updateNewStickerSet(let stickerset): + if boxed { + buffer.appendInt32(1753886890) + } + stickerset.serialize(buffer, true) + break + case .updateNotifySettings(let peer, let notifySettings): + if boxed { + buffer.appendInt32(-1094555409) + } + peer.serialize(buffer, true) + notifySettings.serialize(buffer, true) + break + case .updatePeerBlocked(let peerId, let blocked): + if boxed { + buffer.appendInt32(610945826) + } + peerId.serialize(buffer, true) + blocked.serialize(buffer, true) + break + case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod): + if boxed { + buffer.appendInt32(-1147422299) + } + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} + break + case .updatePeerLocated(let peers): + if boxed { + buffer.appendInt32(-1263546448) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + item.serialize(buffer, true) + } + break + case .updatePeerSettings(let peer, let settings): + if boxed { + buffer.appendInt32(1786671974) + } + peer.serialize(buffer, true) + settings.serialize(buffer, true) + break + case .updatePendingJoinRequests(let peer, let requestsPending, let recentRequesters): + if boxed { + buffer.appendInt32(1885586395) + } + peer.serialize(buffer, true) + serializeInt32(requestsPending, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(recentRequesters.count)) + for item in recentRequesters { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .updatePhoneCall(let phoneCall): + if boxed { + buffer.appendInt32(-1425052898) + } + phoneCall.serialize(buffer, true) + break + case .updatePhoneCallSignalingData(let phoneCallId, let data): + if boxed { + buffer.appendInt32(643940105) + } + serializeInt64(phoneCallId, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + break + case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount): + if boxed { + buffer.appendInt32(1538885128) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(channelId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updatePinnedDialogs(let flags, let folderId, let order): + if boxed { + buffer.appendInt32(-99664734) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order!.count)) + for item in order! { + item.serialize(buffer, true) + }} + break + case .updatePinnedMessages(let flags, let peer, let messages, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-309990731) + } + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updatePrivacy(let key, let rules): + if boxed { + buffer.appendInt32(-298113238) + } + key.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rules.count)) + for item in rules { + item.serialize(buffer, true) + } + break + case .updatePtsChanged: + if boxed { + buffer.appendInt32(861169551) + } + + break + case .updateReadChannelDiscussionInbox(let flags, let channelId, let topMsgId, let readMaxId, let broadcastId, let broadcastPost): + if boxed { + buffer.appendInt32(-693004986) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(topMsgId, buffer: buffer, boxed: false) + serializeInt32(readMaxId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt64(broadcastId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(broadcastPost!, buffer: buffer, boxed: false)} + break + case .updateReadChannelDiscussionOutbox(let channelId, let topMsgId, let readMaxId): + if boxed { + buffer.appendInt32(1767677564) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(topMsgId, buffer: buffer, boxed: false) + serializeInt32(readMaxId, buffer: buffer, boxed: false) + break + case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): + if boxed { + buffer.appendInt32(-1842450928) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + break + case .updateReadChannelOutbox(let channelId, let maxId): + if boxed { + buffer.appendInt32(-1218471511) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + break + case .updateReadFeaturedEmojiStickers: + if boxed { + buffer.appendInt32(-78886548) + } + + break + case .updateReadFeaturedStickers: + if boxed { + buffer.appendInt32(1461528386) + } + + break + case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-1667805217) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + peer.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): + if boxed { + buffer.appendInt32(791617983) + } + peer.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateReadMessagesContents(let messages, let pts, let ptsCount): + if boxed { + buffer.appendInt32(1757493555) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateRecentStickers: + if boxed { + buffer.appendInt32(-1706939360) + } + + break + case .updateSavedGifs: + if boxed { + buffer.appendInt32(-1821035490) + } + + break + case .updateSavedRingtones: + if boxed { + buffer.appendInt32(1960361625) + } + + break + case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities): + if boxed { + buffer.appendInt32(-337352679) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(inboxDate!, buffer: buffer, boxed: false)} + serializeString(type, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + media.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + break + case .updateStickerSets: + if boxed { + buffer.appendInt32(1135492588) + } + + break + case .updateStickerSetsOrder(let flags, let order): + if boxed { + buffer.appendInt32(196268545) + } + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .updateTheme(let theme): + if boxed { + buffer.appendInt32(-2112423005) + } + theme.serialize(buffer, true) + break + case .updateTranscribedAudio(let flags, let peer, let msgId, let transcriptionId, let text): + if boxed { + buffer.appendInt32(8703322) + } + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt64(transcriptionId, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + case .updateUserName(let userId, let firstName, let lastName, let username): + if boxed { + buffer.appendInt32(-1007549728) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(firstName, buffer: buffer, boxed: false) + serializeString(lastName, buffer: buffer, boxed: false) + serializeString(username, buffer: buffer, boxed: false) + break + case .updateUserPhone(let userId, let phone): + if boxed { + buffer.appendInt32(88680979) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(phone, buffer: buffer, boxed: false) + break + case .updateUserPhoto(let userId, let date, let photo, let previous): + if boxed { + buffer.appendInt32(-232290676) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + photo.serialize(buffer, true) + previous.serialize(buffer, true) + break + case .updateUserStatus(let userId, let status): + if boxed { + buffer.appendInt32(-440534818) + } + serializeInt64(userId, buffer: buffer, boxed: false) + status.serialize(buffer, true) + break + case .updateUserTyping(let userId, let action): + if boxed { + buffer.appendInt32(-1071741569) + } + serializeInt64(userId, buffer: buffer, boxed: false) + action.serialize(buffer, true) + break + case .updateWebPage(let webpage, let pts, let ptsCount): + if boxed { + buffer.appendInt32(2139689491) + } + webpage.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + case .updateWebViewResultSent(let queryId): + if boxed { + buffer.appendInt32(361936797) + } + serializeInt64(queryId, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .updateAttachMenuBots: + return ("updateAttachMenuBots", []) + case .updateBotCallbackQuery(let flags, let queryId, let userId, let peer, let msgId, let chatInstance, let data, let gameShortName): + return ("updateBotCallbackQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("chatInstance", String(describing: chatInstance)), ("data", String(describing: data)), ("gameShortName", String(describing: gameShortName))]) + case .updateBotChatInviteRequester(let peer, let date, let userId, let about, let invite, let qts): + return ("updateBotChatInviteRequester", [("peer", String(describing: peer)), ("date", String(describing: date)), ("userId", String(describing: userId)), ("about", String(describing: about)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) + case .updateBotCommands(let peer, let botId, let commands): + return ("updateBotCommands", [("peer", String(describing: peer)), ("botId", String(describing: botId)), ("commands", String(describing: commands))]) + case .updateBotInlineQuery(let flags, let queryId, let userId, let query, let geo, let peerType, let offset): + return ("updateBotInlineQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("query", String(describing: query)), ("geo", String(describing: geo)), ("peerType", String(describing: peerType)), ("offset", String(describing: offset))]) + case .updateBotInlineSend(let flags, let userId, let query, let geo, let id, let msgId): + return ("updateBotInlineSend", [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("query", String(describing: query)), ("geo", String(describing: geo)), ("id", String(describing: id)), ("msgId", String(describing: msgId))]) + case .updateBotMenuButton(let botId, let button): + return ("updateBotMenuButton", [("botId", String(describing: botId)), ("button", String(describing: button))]) + case .updateBotPrecheckoutQuery(let flags, let queryId, let userId, let payload, let info, let shippingOptionId, let currency, let totalAmount): + return ("updateBotPrecheckoutQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("payload", String(describing: payload)), ("info", String(describing: info)), ("shippingOptionId", String(describing: shippingOptionId)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount))]) + case .updateBotShippingQuery(let queryId, let userId, let payload, let shippingAddress): + return ("updateBotShippingQuery", [("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("payload", String(describing: payload)), ("shippingAddress", String(describing: shippingAddress))]) + case .updateBotStopped(let userId, let date, let stopped, let qts): + return ("updateBotStopped", [("userId", String(describing: userId)), ("date", String(describing: date)), ("stopped", String(describing: stopped)), ("qts", String(describing: qts))]) + case .updateBotWebhookJSON(let data): + return ("updateBotWebhookJSON", [("data", String(describing: data))]) + case .updateBotWebhookJSONQuery(let queryId, let data, let timeout): + return ("updateBotWebhookJSONQuery", [("queryId", String(describing: queryId)), ("data", String(describing: data)), ("timeout", String(describing: timeout))]) + case .updateChannel(let channelId): + return ("updateChannel", [("channelId", String(describing: channelId))]) + case .updateChannelAvailableMessages(let channelId, let availableMinId): + return ("updateChannelAvailableMessages", [("channelId", String(describing: channelId)), ("availableMinId", String(describing: availableMinId))]) + case .updateChannelMessageForwards(let channelId, let id, let forwards): + return ("updateChannelMessageForwards", [("channelId", String(describing: channelId)), ("id", String(describing: id)), ("forwards", String(describing: forwards))]) + case .updateChannelMessageViews(let channelId, let id, let views): + return ("updateChannelMessageViews", [("channelId", String(describing: channelId)), ("id", String(describing: id)), ("views", String(describing: views))]) + case .updateChannelParticipant(let flags, let channelId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): + return ("updateChannelParticipant", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("date", String(describing: date)), ("actorId", String(describing: actorId)), ("userId", String(describing: userId)), ("prevParticipant", String(describing: prevParticipant)), ("newParticipant", String(describing: newParticipant)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) + case .updateChannelReadMessagesContents(let channelId, let messages): + return ("updateChannelReadMessagesContents", [("channelId", String(describing: channelId)), ("messages", String(describing: messages))]) + case .updateChannelTooLong(let flags, let channelId, let pts): + return ("updateChannelTooLong", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("pts", String(describing: pts))]) + case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let fromId, let action): + return ("updateChannelUserTyping", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("fromId", String(describing: fromId)), ("action", String(describing: action))]) + case .updateChannelWebPage(let channelId, let webpage, let pts, let ptsCount): + return ("updateChannelWebPage", [("channelId", String(describing: channelId)), ("webpage", String(describing: webpage)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateChat(let chatId): + return ("updateChat", [("chatId", String(describing: chatId))]) + case .updateChatDefaultBannedRights(let peer, let defaultBannedRights, let version): + return ("updateChatDefaultBannedRights", [("peer", String(describing: peer)), ("defaultBannedRights", String(describing: defaultBannedRights)), ("version", String(describing: version))]) + case .updateChatParticipant(let flags, let chatId, let date, let actorId, let userId, let prevParticipant, let newParticipant, let invite, let qts): + return ("updateChatParticipant", [("flags", String(describing: flags)), ("chatId", String(describing: chatId)), ("date", String(describing: date)), ("actorId", String(describing: actorId)), ("userId", String(describing: userId)), ("prevParticipant", String(describing: prevParticipant)), ("newParticipant", String(describing: newParticipant)), ("invite", String(describing: invite)), ("qts", String(describing: qts))]) + case .updateChatParticipantAdd(let chatId, let userId, let inviterId, let date, let version): + return ("updateChatParticipantAdd", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("inviterId", String(describing: inviterId)), ("date", String(describing: date)), ("version", String(describing: version))]) + case .updateChatParticipantAdmin(let chatId, let userId, let isAdmin, let version): + return ("updateChatParticipantAdmin", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("isAdmin", String(describing: isAdmin)), ("version", String(describing: version))]) + case .updateChatParticipantDelete(let chatId, let userId, let version): + return ("updateChatParticipantDelete", [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("version", String(describing: version))]) + case .updateChatParticipants(let participants): + return ("updateChatParticipants", [("participants", String(describing: participants))]) + case .updateChatUserTyping(let chatId, let fromId, let action): + return ("updateChatUserTyping", [("chatId", String(describing: chatId)), ("fromId", String(describing: fromId)), ("action", String(describing: action))]) + case .updateConfig: + return ("updateConfig", []) + case .updateContactsReset: + return ("updateContactsReset", []) + case .updateDcOptions(let dcOptions): + return ("updateDcOptions", [("dcOptions", String(describing: dcOptions))]) + case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): + return ("updateDeleteChannelMessages", [("channelId", String(describing: channelId)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateDeleteMessages(let messages, let pts, let ptsCount): + return ("updateDeleteMessages", [("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateDeleteScheduledMessages(let peer, let messages): + return ("updateDeleteScheduledMessages", [("peer", String(describing: peer)), ("messages", String(describing: messages))]) + case .updateDialogFilter(let flags, let id, let filter): + return ("updateDialogFilter", [("flags", String(describing: flags)), ("id", String(describing: id)), ("filter", String(describing: filter))]) + case .updateDialogFilterOrder(let order): + return ("updateDialogFilterOrder", [("order", String(describing: order))]) + case .updateDialogFilters: + return ("updateDialogFilters", []) + case .updateDialogPinned(let flags, let folderId, let peer): + return ("updateDialogPinned", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer))]) + case .updateDialogUnreadMark(let flags, let peer): + return ("updateDialogUnreadMark", [("flags", String(describing: flags)), ("peer", String(describing: peer))]) + case .updateDraftMessage(let peer, let draft): + return ("updateDraftMessage", [("peer", String(describing: peer)), ("draft", String(describing: draft))]) + case .updateEditChannelMessage(let message, let pts, let ptsCount): + return ("updateEditChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateEditMessage(let message, let pts, let ptsCount): + return ("updateEditMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateEncryptedChatTyping(let chatId): + return ("updateEncryptedChatTyping", [("chatId", String(describing: chatId))]) + case .updateEncryptedMessagesRead(let chatId, let maxDate, let date): + return ("updateEncryptedMessagesRead", [("chatId", String(describing: chatId)), ("maxDate", String(describing: maxDate)), ("date", String(describing: date))]) + case .updateEncryption(let chat, let date): + return ("updateEncryption", [("chat", String(describing: chat)), ("date", String(describing: date))]) + case .updateFavedStickers: + return ("updateFavedStickers", []) + case .updateFolderPeers(let folderPeers, let pts, let ptsCount): + return ("updateFolderPeers", [("folderPeers", String(describing: folderPeers)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateGeoLiveViewed(let peer, let msgId): + return ("updateGeoLiveViewed", [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]) + case .updateGroupCall(let chatId, let call): + return ("updateGroupCall", [("chatId", String(describing: chatId)), ("call", String(describing: call))]) + case .updateGroupCallConnection(let flags, let params): + return ("updateGroupCallConnection", [("flags", String(describing: flags)), ("params", String(describing: params))]) + case .updateGroupCallParticipants(let call, let participants, let version): + return ("updateGroupCallParticipants", [("call", String(describing: call)), ("participants", String(describing: participants)), ("version", String(describing: version))]) + case .updateInlineBotCallbackQuery(let flags, let queryId, let userId, let msgId, let chatInstance, let data, let gameShortName): + return ("updateInlineBotCallbackQuery", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("userId", String(describing: userId)), ("msgId", String(describing: msgId)), ("chatInstance", String(describing: chatInstance)), ("data", String(describing: data)), ("gameShortName", String(describing: gameShortName))]) + case .updateLangPack(let difference): + return ("updateLangPack", [("difference", String(describing: difference))]) + case .updateLangPackTooLong(let langCode): + return ("updateLangPackTooLong", [("langCode", String(describing: langCode))]) + case .updateLoginToken: + return ("updateLoginToken", []) + case .updateMessageID(let id, let randomId): + return ("updateMessageID", [("id", String(describing: id)), ("randomId", String(describing: randomId))]) + case .updateMessagePoll(let flags, let pollId, let poll, let results): + return ("updateMessagePoll", [("flags", String(describing: flags)), ("pollId", String(describing: pollId)), ("poll", String(describing: poll)), ("results", String(describing: results))]) + case .updateMessagePollVote(let pollId, let userId, let options, let qts): + return ("updateMessagePollVote", [("pollId", String(describing: pollId)), ("userId", String(describing: userId)), ("options", String(describing: options)), ("qts", String(describing: qts))]) + case .updateMessageReactions(let peer, let msgId, let reactions): + return ("updateMessageReactions", [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reactions", String(describing: reactions))]) + case .updateNewChannelMessage(let message, let pts, let ptsCount): + return ("updateNewChannelMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateNewEncryptedMessage(let message, let qts): + return ("updateNewEncryptedMessage", [("message", String(describing: message)), ("qts", String(describing: qts))]) + case .updateNewMessage(let message, let pts, let ptsCount): + return ("updateNewMessage", [("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateNewScheduledMessage(let message): + return ("updateNewScheduledMessage", [("message", String(describing: message))]) + case .updateNewStickerSet(let stickerset): + return ("updateNewStickerSet", [("stickerset", String(describing: stickerset))]) + case .updateNotifySettings(let peer, let notifySettings): + return ("updateNotifySettings", [("peer", String(describing: peer)), ("notifySettings", String(describing: notifySettings))]) + case .updatePeerBlocked(let peerId, let blocked): + return ("updatePeerBlocked", [("peerId", String(describing: peerId)), ("blocked", String(describing: blocked))]) + case .updatePeerHistoryTTL(let flags, let peer, let ttlPeriod): + return ("updatePeerHistoryTTL", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("ttlPeriod", String(describing: ttlPeriod))]) + case .updatePeerLocated(let peers): + return ("updatePeerLocated", [("peers", String(describing: peers))]) + case .updatePeerSettings(let peer, let settings): + return ("updatePeerSettings", [("peer", String(describing: peer)), ("settings", String(describing: settings))]) + case .updatePendingJoinRequests(let peer, let requestsPending, let recentRequesters): + return ("updatePendingJoinRequests", [("peer", String(describing: peer)), ("requestsPending", String(describing: requestsPending)), ("recentRequesters", String(describing: recentRequesters))]) + case .updatePhoneCall(let phoneCall): + return ("updatePhoneCall", [("phoneCall", String(describing: phoneCall))]) + case .updatePhoneCallSignalingData(let phoneCallId, let data): + return ("updatePhoneCallSignalingData", [("phoneCallId", String(describing: phoneCallId)), ("data", String(describing: data))]) + case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount): + return ("updatePinnedChannelMessages", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updatePinnedDialogs(let flags, let folderId, let order): + return ("updatePinnedDialogs", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("order", String(describing: order))]) + case .updatePinnedMessages(let flags, let peer, let messages, let pts, let ptsCount): + return ("updatePinnedMessages", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updatePrivacy(let key, let rules): + return ("updatePrivacy", [("key", String(describing: key)), ("rules", String(describing: rules))]) + case .updatePtsChanged: + return ("updatePtsChanged", []) + case .updateReadChannelDiscussionInbox(let flags, let channelId, let topMsgId, let readMaxId, let broadcastId, let broadcastPost): + return ("updateReadChannelDiscussionInbox", [("flags", String(describing: flags)), ("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("readMaxId", String(describing: readMaxId)), ("broadcastId", String(describing: broadcastId)), ("broadcastPost", String(describing: broadcastPost))]) + case .updateReadChannelDiscussionOutbox(let channelId, let topMsgId, let readMaxId): + return ("updateReadChannelDiscussionOutbox", [("channelId", String(describing: channelId)), ("topMsgId", String(describing: topMsgId)), ("readMaxId", String(describing: readMaxId))]) + case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): + return ("updateReadChannelInbox", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("channelId", String(describing: channelId)), ("maxId", String(describing: maxId)), ("stillUnreadCount", String(describing: stillUnreadCount)), ("pts", String(describing: pts))]) + case .updateReadChannelOutbox(let channelId, let maxId): + return ("updateReadChannelOutbox", [("channelId", String(describing: channelId)), ("maxId", String(describing: maxId))]) + case .updateReadFeaturedEmojiStickers: + return ("updateReadFeaturedEmojiStickers", []) + case .updateReadFeaturedStickers: + return ("updateReadFeaturedStickers", []) + case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): + return ("updateReadHistoryInbox", [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("stillUnreadCount", String(describing: stillUnreadCount)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): + return ("updateReadHistoryOutbox", [("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateReadMessagesContents(let messages, let pts, let ptsCount): + return ("updateReadMessagesContents", [("messages", String(describing: messages)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateRecentStickers: + return ("updateRecentStickers", []) + case .updateSavedGifs: + return ("updateSavedGifs", []) + case .updateSavedRingtones: + return ("updateSavedRingtones", []) + case .updateServiceNotification(let flags, let inboxDate, let type, let message, let media, let entities): + return ("updateServiceNotification", [("flags", String(describing: flags)), ("inboxDate", String(describing: inboxDate)), ("type", String(describing: type)), ("message", String(describing: message)), ("media", String(describing: media)), ("entities", String(describing: entities))]) + case .updateStickerSets: + return ("updateStickerSets", []) + case .updateStickerSetsOrder(let flags, let order): + return ("updateStickerSetsOrder", [("flags", String(describing: flags)), ("order", String(describing: order))]) + case .updateTheme(let theme): + return ("updateTheme", [("theme", String(describing: theme))]) + case .updateTranscribedAudio(let flags, let peer, let msgId, let transcriptionId, let text): + return ("updateTranscribedAudio", [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("transcriptionId", String(describing: transcriptionId)), ("text", String(describing: text))]) + case .updateUserName(let userId, let firstName, let lastName, let username): + return ("updateUserName", [("userId", String(describing: userId)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username))]) + case .updateUserPhone(let userId, let phone): + return ("updateUserPhone", [("userId", String(describing: userId)), ("phone", String(describing: phone))]) + case .updateUserPhoto(let userId, let date, let photo, let previous): + return ("updateUserPhoto", [("userId", String(describing: userId)), ("date", String(describing: date)), ("photo", String(describing: photo)), ("previous", String(describing: previous))]) + case .updateUserStatus(let userId, let status): + return ("updateUserStatus", [("userId", String(describing: userId)), ("status", String(describing: status))]) + case .updateUserTyping(let userId, let action): + return ("updateUserTyping", [("userId", String(describing: userId)), ("action", String(describing: action))]) + case .updateWebPage(let webpage, let pts, let ptsCount): + return ("updateWebPage", [("webpage", String(describing: webpage)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + case .updateWebViewResultSent(let queryId): + return ("updateWebViewResultSent", [("queryId", String(describing: queryId))]) + } + } + + public static func parse_updateAttachMenuBots(_ reader: BufferReader) -> Update? { + return Api.Update.updateAttachMenuBots + } + public static func parse_updateBotCallbackQuery(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Api.Peer? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _5: Int32? + _5 = reader.readInt32() + var _6: Int64? + _6 = reader.readInt64() + var _7: Buffer? + if Int(_1!) & Int(1 << 0) != 0 {_7 = parseBytes(reader) } + var _8: String? + if Int(_1!) & Int(1 << 1) != 0 {_8 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.WebAuthorization.webAuthorization(hash: _1!, botId: _2!, domain: _3!, browser: _4!, platform: _5!, dateCreated: _6!, dateActive: _7!, ip: _8!, region: _9!) + let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.Update.updateBotCallbackQuery(flags: _1!, queryId: _2!, userId: _3!, peer: _4!, msgId: _5!, chatInstance: _6!, data: _7, gameShortName: _8) } else { return nil } } - - } -} -public extension Api { - enum WebDocument: TypeConstructorDescription { - case webDocument(url: String, accessHash: Int64, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) - case webDocumentNoProxy(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .webDocument(let url, let accessHash, let size, let mimeType, let attributes): - if boxed { - buffer.appendInt32(475467473) - } - serializeString(url, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(size, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(attributes.count)) - for item in attributes { - item.serialize(buffer, true) - } - break - case .webDocumentNoProxy(let url, let size, let mimeType, let attributes): - if boxed { - buffer.appendInt32(-104284986) - } - serializeString(url, buffer: buffer, boxed: false) - serializeInt32(size, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(attributes.count)) - for item in attributes { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .webDocument(let url, let accessHash, let size, let mimeType, let attributes): - return ("webDocument", [("url", String(describing: url)), ("accessHash", String(describing: accessHash)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) - case .webDocumentNoProxy(let url, let size, let mimeType, let attributes): - return ("webDocumentNoProxy", [("url", String(describing: url)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) - } - } - - public static func parse_webDocument(_ reader: BufferReader) -> WebDocument? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() + public static func parse_updateBotChatInviteRequester(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() var _4: String? _4 = parseString(reader) - var _5: [Api.DocumentAttribute]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) + var _5: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite } + var _6: Int32? + _6 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.WebDocument.webDocument(url: _1!, accessHash: _2!, size: _3!, mimeType: _4!, attributes: _5!) + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateBotChatInviteRequester(peer: _1!, date: _2!, userId: _3!, about: _4!, invite: _5!, qts: _6!) } else { return nil } } - public static func parse_webDocumentNoProxy(_ reader: BufferReader) -> WebDocument? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: [Api.DocumentAttribute]? + public static func parse_updateBotCommands(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int64? + _2 = reader.readInt64() + var _3: [Api.BotCommand]? if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.WebDocument.webDocumentNoProxy(url: _1!, size: _2!, mimeType: _3!, attributes: _4!) + if _c1 && _c2 && _c3 { + return Api.Update.updateBotCommands(peer: _1!, botId: _2!, commands: _3!) } else { return nil } } - - } -} -public extension Api { - enum WebPage: TypeConstructorDescription { - case webPage(flags: Int32, id: Int64, url: String, displayUrl: String, hash: Int32, type: String?, siteName: String?, title: String?, description: String?, photo: Api.Photo?, embedUrl: String?, embedType: String?, embedWidth: Int32?, embedHeight: Int32?, duration: Int32?, author: String?, document: Api.Document?, cachedPage: Api.Page?, attributes: [Api.WebPageAttribute]?) - case webPageEmpty(id: Int64) - case webPageNotModified(flags: Int32, cachedPageViews: Int32?) - case webPagePending(id: Int64, date: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .webPage(let flags, let id, let url, let displayUrl, let hash, let type, let siteName, let title, let description, let photo, let embedUrl, let embedType, let embedWidth, let embedHeight, let duration, let author, let document, let cachedPage, let attributes): - if boxed { - buffer.appendInt32(-392411726) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(id, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - serializeString(displayUrl, buffer: buffer, boxed: false) - serializeInt32(hash, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(type!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(siteName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(description!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {photo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 5) != 0 {serializeString(embedUrl!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 5) != 0 {serializeString(embedType!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(embedWidth!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(embedHeight!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 7) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 8) != 0 {serializeString(author!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 9) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 10) != 0 {cachedPage!.serialize(buffer, true)} - if Int(flags) & Int(1 << 12) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(attributes!.count)) - for item in attributes! { - item.serialize(buffer, true) - }} - break - case .webPageEmpty(let id): - if boxed { - buffer.appendInt32(-350980120) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - case .webPageNotModified(let flags, let cachedPageViews): - if boxed { - buffer.appendInt32(1930545681) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(cachedPageViews!, buffer: buffer, boxed: false)} - break - case .webPagePending(let id, let date): - if boxed { - buffer.appendInt32(-981018084) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .webPage(let flags, let id, let url, let displayUrl, let hash, let type, let siteName, let title, let description, let photo, let embedUrl, let embedType, let embedWidth, let embedHeight, let duration, let author, let document, let cachedPage, let attributes): - return ("webPage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("url", String(describing: url)), ("displayUrl", String(describing: displayUrl)), ("hash", String(describing: hash)), ("type", String(describing: type)), ("siteName", String(describing: siteName)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("embedUrl", String(describing: embedUrl)), ("embedType", String(describing: embedType)), ("embedWidth", String(describing: embedWidth)), ("embedHeight", String(describing: embedHeight)), ("duration", String(describing: duration)), ("author", String(describing: author)), ("document", String(describing: document)), ("cachedPage", String(describing: cachedPage)), ("attributes", String(describing: attributes))]) - case .webPageEmpty(let id): - return ("webPageEmpty", [("id", String(describing: id))]) - case .webPageNotModified(let flags, let cachedPageViews): - return ("webPageNotModified", [("flags", String(describing: flags)), ("cachedPageViews", String(describing: cachedPageViews))]) - case .webPagePending(let id, let date): - return ("webPagePending", [("id", String(describing: id)), ("date", String(describing: date))]) - } - } - - public static func parse_webPage(_ reader: BufferReader) -> WebPage? { + public static func parse_updateBotInlineQuery(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: Api.GeoPoint? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } } + var _6: Api.InlineQueryPeerType? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.InlineQueryPeerType + } } + var _7: String? + _7 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.Update.updateBotInlineQuery(flags: _1!, queryId: _2!, userId: _3!, query: _4!, geo: _5, peerType: _6, offset: _7!) + } + else { + return nil + } + } + public static func parse_updateBotInlineSend(_ reader: BufferReader) -> Update? { var _1: Int32? _1 = reader.readInt32() var _2: Int64? _2 = reader.readInt64() var _3: String? _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: Int32? - _5 = reader.readInt32() + var _4: Api.GeoPoint? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } } + var _5: String? + _5 = parseString(reader) + var _6: Api.InputBotInlineMessageID? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID + } } + 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 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateBotInlineSend(flags: _1!, userId: _2!, query: _3!, geo: _4, id: _5!, msgId: _6) + } + else { + return nil + } + } + public static func parse_updateBotMenuButton(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.BotMenuButton? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.BotMenuButton + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateBotMenuButton(botId: _1!, button: _2!) + } + else { + return nil + } + } + public static func parse_updateBotPrecheckoutQuery(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Buffer? + _4 = parseBytes(reader) + var _5: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } var _6: String? - if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } + if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } var _7: String? - if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) } - var _8: String? - if Int(_1!) & Int(1 << 2) != 0 {_8 = parseString(reader) } - var _9: String? - if Int(_1!) & Int(1 << 3) != 0 {_9 = parseString(reader) } - var _10: Api.Photo? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.Photo + _7 = parseString(reader) + var _8: Int64? + _8 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.Update.updateBotPrecheckoutQuery(flags: _1!, queryId: _2!, userId: _3!, payload: _4!, info: _5, shippingOptionId: _6, currency: _7!, totalAmount: _8!) + } + else { + return nil + } + } + public static func parse_updateBotShippingQuery(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Buffer? + _3 = parseBytes(reader) + var _4: Api.PostAddress? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.PostAddress + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateBotShippingQuery(queryId: _1!, userId: _2!, payload: _3!, shippingAddress: _4!) + } + else { + return nil + } + } + public static func parse_updateBotStopped(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.Bool? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Bool + } + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateBotStopped(userId: _1!, date: _2!, stopped: _3!, qts: _4!) + } + else { + return nil + } + } + public static func parse_updateBotWebhookJSON(_ reader: BufferReader) -> Update? { + var _1: Api.DataJSON? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateBotWebhookJSON(data: _1!) + } + else { + return nil + } + } + public static func parse_updateBotWebhookJSONQuery(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.DataJSON? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateBotWebhookJSONQuery(queryId: _1!, data: _2!, timeout: _3!) + } + else { + return nil + } + } + public static func parse_updateChannel(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateChannel(channelId: _1!) + } + else { + return nil + } + } + public static func parse_updateChannelAvailableMessages(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateChannelAvailableMessages(channelId: _1!, availableMinId: _2!) + } + else { + return nil + } + } + public static func parse_updateChannelMessageForwards(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChannelMessageForwards(channelId: _1!, id: _2!, forwards: _3!) + } + else { + return nil + } + } + public static func parse_updateChannelMessageViews(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChannelMessageViews(channelId: _1!, id: _2!, views: _3!) + } + else { + return nil + } + } + public static func parse_updateChannelParticipant(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int64? + _4 = reader.readInt64() + var _5: Int64? + _5 = reader.readInt64() + var _6: Api.ChannelParticipant? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant } } - var _11: String? - if Int(_1!) & Int(1 << 5) != 0 {_11 = parseString(reader) } - var _12: String? - if Int(_1!) & Int(1 << 5) != 0 {_12 = parseString(reader) } - var _13: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_13 = reader.readInt32() } - var _14: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_14 = reader.readInt32() } - var _15: Int32? - if Int(_1!) & Int(1 << 7) != 0 {_15 = reader.readInt32() } - var _16: String? - if Int(_1!) & Int(1 << 8) != 0 {_16 = parseString(reader) } - var _17: Api.Document? - if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { - _17 = Api.parse(reader, signature: signature) as? Api.Document + var _7: Api.ChannelParticipant? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant } } - var _18: Api.Page? - if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() { - _18 = Api.parse(reader, signature: signature) as? Api.Page - } } - var _19: [Api.WebPageAttribute]? - if Int(_1!) & Int(1 << 12) != 0 {if let _ = reader.readInt32() { - _19 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WebPageAttribute.self) + var _8: Api.ExportedChatInvite? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite } } + var _9: Int32? + _9 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -1330,50 +2121,1119 @@ public extension Api { let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 3) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 5) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 5) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 6) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 6) == 0) || _14 != nil - let _c15 = (Int(_1!) & Int(1 << 7) == 0) || _15 != nil - let _c16 = (Int(_1!) & Int(1 << 8) == 0) || _16 != nil - let _c17 = (Int(_1!) & Int(1 << 9) == 0) || _17 != nil - let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil - let _c19 = (Int(_1!) & Int(1 << 12) == 0) || _19 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 { - return Api.WebPage.webPage(flags: _1!, id: _2!, url: _3!, displayUrl: _4!, hash: _5!, type: _6, siteName: _7, title: _8, description: _9, photo: _10, embedUrl: _11, embedType: _12, embedWidth: _13, embedHeight: _14, duration: _15, author: _16, document: _17, cachedPage: _18, attributes: _19) + let _c9 = _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.Update.updateChannelParticipant(flags: _1!, channelId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!) } else { return nil } } - public static func parse_webPageEmpty(_ reader: BufferReader) -> WebPage? { + public static func parse_updateChannelReadMessagesContents(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Int32]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateChannelReadMessagesContents(channelId: _1!, messages: _2!) + } + else { + return nil + } + } + public static func parse_updateChannelTooLong(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChannelTooLong(flags: _1!, channelId: _2!, pts: _3) + } + else { + return nil + } + } + public static func parse_updateChannelUserTyping(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Api.Peer? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _5: Api.SendMessageAction? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.SendMessageAction + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updateChannelUserTyping(flags: _1!, channelId: _2!, topMsgId: _3, fromId: _4!, action: _5!) + } + else { + return nil + } + } + public static func parse_updateChannelWebPage(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.WebPage? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.WebPage + } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateChannelWebPage(channelId: _1!, webpage: _2!, pts: _3!, ptsCount: _4!) + } + else { + return nil + } + } + public static func parse_updateChat(_ reader: BufferReader) -> Update? { var _1: Int64? _1 = reader.readInt64() let _c1 = _1 != nil if _c1 { - return Api.WebPage.webPageEmpty(id: _1!) + return Api.Update.updateChat(chatId: _1!) } else { return nil } } - public static func parse_webPageNotModified(_ reader: BufferReader) -> WebPage? { + public static func parse_updateChatDefaultBannedRights(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Api.ChatBannedRights? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.ChatBannedRights + } + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChatDefaultBannedRights(peer: _1!, defaultBannedRights: _2!, version: _3!) + } + else { + return nil + } + } + public static func parse_updateChatParticipant(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int64? + _4 = reader.readInt64() + var _5: Int64? + _5 = reader.readInt64() + var _6: Api.ChatParticipant? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.ChatParticipant + } } + var _7: Api.ChatParticipant? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.ChatParticipant + } } + var _8: Api.ExportedChatInvite? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } } + var _9: Int32? + _9 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil + let _c9 = _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.Update.updateChatParticipant(flags: _1!, chatId: _2!, date: _3!, actorId: _4!, userId: _5!, prevParticipant: _6, newParticipant: _7, invite: _8, qts: _9!) + } + else { + return nil + } + } + public static func parse_updateChatParticipantAdd(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updateChatParticipantAdd(chatId: _1!, userId: _2!, inviterId: _3!, date: _4!, version: _5!) + } + else { + return nil + } + } + public static func parse_updateChatParticipantAdmin(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.Bool? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Bool + } + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateChatParticipantAdmin(chatId: _1!, userId: _2!, isAdmin: _3!, version: _4!) + } + else { + return nil + } + } + public static func parse_updateChatParticipantDelete(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChatParticipantDelete(chatId: _1!, userId: _2!, version: _3!) + } + else { + return nil + } + } + public static func parse_updateChatParticipants(_ reader: BufferReader) -> Update? { + var _1: Api.ChatParticipants? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.ChatParticipants + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateChatParticipants(participants: _1!) + } + else { + return nil + } + } + public static func parse_updateChatUserTyping(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _3: Api.SendMessageAction? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.SendMessageAction + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateChatUserTyping(chatId: _1!, fromId: _2!, action: _3!) + } + else { + return nil + } + } + public static func parse_updateConfig(_ reader: BufferReader) -> Update? { + return Api.Update.updateConfig + } + public static func parse_updateContactsReset(_ reader: BufferReader) -> Update? { + return Api.Update.updateContactsReset + } + public static func parse_updateDcOptions(_ reader: BufferReader) -> Update? { + var _1: [Api.DcOption]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DcOption.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateDcOptions(dcOptions: _1!) + } + else { + return nil + } + } + public static func parse_updateDeleteChannelMessages(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Int32]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateDeleteChannelMessages(channelId: _1!, messages: _2!, pts: _3!, ptsCount: _4!) + } + else { + return nil + } + } + public static func parse_updateDeleteMessages(_ reader: BufferReader) -> Update? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateDeleteMessages(messages: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateDeleteScheduledMessages(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: [Int32]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateDeleteScheduledMessages(peer: _1!, messages: _2!) + } + else { + return nil + } + } + public static func parse_updateDialogFilter(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.DialogFilter? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.DialogFilter + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateDialogFilter(flags: _1!, id: _2!, filter: _3) + } + else { + return nil + } + } + public static func parse_updateDialogFilterOrder(_ reader: BufferReader) -> Update? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateDialogFilterOrder(order: _1!) + } + else { + return nil + } + } + public static func parse_updateDialogFilters(_ reader: BufferReader) -> Update? { + return Api.Update.updateDialogFilters + } + public static func parse_updateDialogPinned(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: Api.DialogPeer? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.DialogPeer + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateDialogPinned(flags: _1!, folderId: _2, peer: _3!) + } + else { + return nil + } + } + public static func parse_updateDialogUnreadMark(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.DialogPeer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DialogPeer + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateDialogUnreadMark(flags: _1!, peer: _2!) + } + else { + return nil + } + } + public static func parse_updateDraftMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Api.DraftMessage? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DraftMessage + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateDraftMessage(peer: _1!, draft: _2!) + } + else { + return nil + } + } + public static func parse_updateEditChannelMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Message? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Message + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateEditChannelMessage(message: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateEditMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Message? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Message + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateEditMessage(message: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateEncryptedChatTyping(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateEncryptedChatTyping(chatId: _1!) + } + else { + return nil + } + } + public static func parse_updateEncryptedMessagesRead(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateEncryptedMessagesRead(chatId: _1!, maxDate: _2!, date: _3!) + } + else { + return nil + } + } + public static func parse_updateEncryption(_ reader: BufferReader) -> Update? { + var _1: Api.EncryptedChat? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.EncryptedChat + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateEncryption(chat: _1!, date: _2!) + } + else { + return nil + } + } + public static func parse_updateFavedStickers(_ reader: BufferReader) -> Update? { + return Api.Update.updateFavedStickers + } + public static func parse_updateFolderPeers(_ reader: BufferReader) -> Update? { + var _1: [Api.FolderPeer]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.FolderPeer.self) + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateFolderPeers(folderPeers: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateGeoLiveViewed(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateGeoLiveViewed(peer: _1!, msgId: _2!) + } + else { + return nil + } + } + public static func parse_updateGroupCall(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.GroupCall? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.GroupCall + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateGroupCall(chatId: _1!, call: _2!) + } + else { + return nil + } + } + public static func parse_updateGroupCallConnection(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.DataJSON? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateGroupCallConnection(flags: _1!, params: _2!) + } + else { + return nil + } + } + public static func parse_updateGroupCallParticipants(_ reader: BufferReader) -> Update? { + var _1: Api.InputGroupCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGroupCall + } + var _2: [Api.GroupCallParticipant]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) + } + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateGroupCallParticipants(call: _1!, participants: _2!, version: _3!) + } + else { + return nil + } + } + public static func parse_updateInlineBotCallbackQuery(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: Api.InputBotInlineMessageID? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID + } + var _5: Int64? + _5 = reader.readInt64() + var _6: Buffer? + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseBytes(reader) } + var _7: String? + if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.Update.updateInlineBotCallbackQuery(flags: _1!, queryId: _2!, userId: _3!, msgId: _4!, chatInstance: _5!, data: _6, gameShortName: _7) + } + else { + return nil + } + } + public static func parse_updateLangPack(_ reader: BufferReader) -> Update? { + var _1: Api.LangPackDifference? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.LangPackDifference + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateLangPack(difference: _1!) + } + else { + return nil + } + } + public static func parse_updateLangPackTooLong(_ reader: BufferReader) -> Update? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateLangPackTooLong(langCode: _1!) + } + else { + return nil + } + } + public static func parse_updateLoginToken(_ reader: BufferReader) -> Update? { + return Api.Update.updateLoginToken + } + public static func parse_updateMessageID(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateMessageID(id: _1!, randomId: _2!) + } + else { + return nil + } + } + public static func parse_updateMessagePoll(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Api.Poll? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Poll + } } + var _4: Api.PollResults? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.PollResults + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateMessagePoll(flags: _1!, pollId: _2!, poll: _3, results: _4!) + } + else { + return nil + } + } + public static func parse_updateMessagePollVote(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: [Buffer]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self) + } + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateMessagePollVote(pollId: _1!, userId: _2!, options: _3!, qts: _4!) + } + else { + return nil + } + } + public static func parse_updateMessageReactions(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.MessageReactions? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.MessageReactions + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateMessageReactions(peer: _1!, msgId: _2!, reactions: _3!) + } + else { + return nil + } + } + public static func parse_updateNewChannelMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Message? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Message + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateNewChannelMessage(message: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateNewEncryptedMessage(_ reader: BufferReader) -> Update? { + var _1: Api.EncryptedMessage? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.EncryptedMessage + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateNewEncryptedMessage(message: _1!, qts: _2!) + } + else { + return nil + } + } + public static func parse_updateNewMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Message? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Message + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateNewMessage(message: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateNewScheduledMessage(_ reader: BufferReader) -> Update? { + var _1: Api.Message? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Message + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateNewScheduledMessage(message: _1!) + } + else { + return nil + } + } + public static func parse_updateNewStickerSet(_ reader: BufferReader) -> Update? { + var _1: Api.messages.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateNewStickerSet(stickerset: _1!) + } + else { + return nil + } + } + public static func parse_updateNotifySettings(_ reader: BufferReader) -> Update? { + var _1: Api.NotifyPeer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.NotifyPeer + } + var _2: Api.PeerNotifySettings? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateNotifySettings(peer: _1!, notifySettings: _2!) + } + else { + return nil + } + } + public static func parse_updatePeerBlocked(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Api.Bool? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Bool + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updatePeerBlocked(peerId: _1!, blocked: _2!) + } + else { + return nil + } + } + public static func parse_updatePeerHistoryTTL(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updatePeerHistoryTTL(flags: _1!, peer: _2!, ttlPeriod: _3) + } + else { + return nil + } + } + public static func parse_updatePeerLocated(_ reader: BufferReader) -> Update? { + var _1: [Api.PeerLocated]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerLocated.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updatePeerLocated(peers: _1!) + } + else { + return nil + } + } + public static func parse_updatePeerSettings(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Api.PeerSettings? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PeerSettings + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updatePeerSettings(peer: _1!, settings: _2!) + } + else { + return nil + } + } + public static func parse_updatePendingJoinRequests(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + var _3: [Int64]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updatePendingJoinRequests(peer: _1!, requestsPending: _2!, recentRequesters: _3!) + } + else { + return nil + } + } + public static func parse_updatePhoneCall(_ reader: BufferReader) -> Update? { + var _1: Api.PhoneCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updatePhoneCall(phoneCall: _1!) + } + else { + return nil + } + } + public static func parse_updatePhoneCallSignalingData(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updatePhoneCallSignalingData(phoneCallId: _1!, data: _2!) + } + else { + return nil + } + } + public static func parse_updatePinnedChannelMessages(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: [Int32]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updatePinnedChannelMessages(flags: _1!, channelId: _2!, messages: _3!, pts: _4!, ptsCount: _5!) + } + else { + return nil + } + } + public static func parse_updatePinnedDialogs(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: [Api.DialogPeer]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogPeer.self) + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updatePinnedDialogs(flags: _1!, folderId: _2, order: _3) + } + else { + return nil + } + } + public static func parse_updatePinnedMessages(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _3: [Int32]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updatePinnedMessages(flags: _1!, peer: _2!, messages: _3!, pts: _4!, ptsCount: _5!) + } + else { + return nil + } + } + public static func parse_updatePrivacy(_ reader: BufferReader) -> Update? { + var _1: Api.PrivacyKey? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PrivacyKey + } + var _2: [Api.PrivacyRule]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updatePrivacy(key: _1!, rules: _2!) + } + else { + return nil + } + } + public static func parse_updatePtsChanged(_ reader: BufferReader) -> Update? { + return Api.Update.updatePtsChanged + } + public static func parse_updateReadChannelDiscussionInbox(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } + var _6: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateReadChannelDiscussionInbox(flags: _1!, channelId: _2!, topMsgId: _3!, readMaxId: _4!, broadcastId: _5, broadcastPost: _6) + } + else { + return nil + } + } + public static func parse_updateReadChannelDiscussionOutbox(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateReadChannelDiscussionOutbox(channelId: _1!, topMsgId: _2!, readMaxId: _3!) + } + else { + return nil + } + } + public static func parse_updateReadChannelInbox(_ reader: BufferReader) -> Update? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() let _c1 = _1 != nil let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - if _c1 && _c2 { - return Api.WebPage.webPageNotModified(flags: _1!, cachedPageViews: _2) + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateReadChannelInbox(flags: _1!, folderId: _2, channelId: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!) } else { return nil } } - public static func parse_webPagePending(_ reader: BufferReader) -> WebPage? { + public static func parse_updateReadChannelOutbox(_ reader: BufferReader) -> Update? { var _1: Int64? _1 = reader.readInt64() var _2: Int32? @@ -1381,7 +3241,301 @@ public extension Api { let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.WebPage.webPagePending(id: _1!, date: _2!) + return Api.Update.updateReadChannelOutbox(channelId: _1!, maxId: _2!) + } + else { + return nil + } + } + public static func parse_updateReadFeaturedEmojiStickers(_ reader: BufferReader) -> Update? { + return Api.Update.updateReadFeaturedEmojiStickers + } + public static func parse_updateReadFeaturedStickers(_ reader: BufferReader) -> Update? { + return Api.Update.updateReadFeaturedStickers + } + public static func parse_updateReadHistoryInbox(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Api.Peer? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + var _7: Int32? + _7 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.Update.updateReadHistoryInbox(flags: _1!, folderId: _2, peer: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!, ptsCount: _7!) + } + else { + return nil + } + } + public static func parse_updateReadHistoryOutbox(_ reader: BufferReader) -> Update? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateReadHistoryOutbox(peer: _1!, maxId: _2!, pts: _3!, ptsCount: _4!) + } + else { + return nil + } + } + public static func parse_updateReadMessagesContents(_ reader: BufferReader) -> Update? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateReadMessagesContents(messages: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateRecentStickers(_ reader: BufferReader) -> Update? { + return Api.Update.updateRecentStickers + } + public static func parse_updateSavedGifs(_ reader: BufferReader) -> Update? { + return Api.Update.updateSavedGifs + } + public static func parse_updateSavedRingtones(_ reader: BufferReader) -> Update? { + return Api.Update.updateSavedRingtones + } + public static func parse_updateServiceNotification(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Api.MessageMedia? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + var _6: [Api.MessageEntity]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateServiceNotification(flags: _1!, inboxDate: _2, type: _3!, message: _4!, media: _5!, entities: _6!) + } + else { + return nil + } + } + public static func parse_updateStickerSets(_ reader: BufferReader) -> Update? { + return Api.Update.updateStickerSets + } + public static func parse_updateStickerSetsOrder(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Int64]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateStickerSetsOrder(flags: _1!, order: _2!) + } + else { + return nil + } + } + public static func parse_updateTheme(_ reader: BufferReader) -> Update? { + var _1: Api.Theme? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Theme + } + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateTheme(theme: _1!) + } + else { + return nil + } + } + public static func parse_updateTranscribedAudio(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.Peer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int64? + _4 = reader.readInt64() + var _5: String? + _5 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Update.updateTranscribedAudio(flags: _1!, peer: _2!, msgId: _3!, transcriptionId: _4!, text: _5!) + } + else { + return nil + } + } + public static func parse_updateUserName(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateUserName(userId: _1!, firstName: _2!, lastName: _3!, username: _4!) + } + else { + return nil + } + } + public static func parse_updateUserPhone(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateUserPhone(userId: _1!, phone: _2!) + } + else { + return nil + } + } + public static func parse_updateUserPhoto(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.UserProfilePhoto? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto + } + var _4: Api.Bool? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.Bool + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.Update.updateUserPhoto(userId: _1!, date: _2!, photo: _3!, previous: _4!) + } + else { + return nil + } + } + public static func parse_updateUserStatus(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.UserStatus? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.UserStatus + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateUserStatus(userId: _1!, status: _2!) + } + else { + return nil + } + } + public static func parse_updateUserTyping(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Api.SendMessageAction? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.SendMessageAction + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateUserTyping(userId: _1!, action: _2!) + } + else { + return nil + } + } + public static func parse_updateWebPage(_ reader: BufferReader) -> Update? { + var _1: Api.WebPage? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.WebPage + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.Update.updateWebPage(webpage: _1!, pts: _2!, ptsCount: _3!) + } + else { + return nil + } + } + public static func parse_updateWebViewResultSent(_ reader: BufferReader) -> Update? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.Update.updateWebViewResultSent(queryId: _1!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api21.swift b/submodules/TelegramApi/Sources/Api21.swift index bcde2a9b8b..737828ce5d 100644 --- a/submodules/TelegramApi/Sources/Api21.swift +++ b/submodules/TelegramApi/Sources/Api21.swift @@ -1,161 +1,89 @@ public extension Api { - enum WebPageAttribute: TypeConstructorDescription { - case webPageAttributeTheme(flags: Int32, documents: [Api.Document]?, settings: Api.ThemeSettings?) + enum Updates: TypeConstructorDescription { + case updateShort(update: Api.Update, date: Int32) + case updateShortChatMessage(flags: Int32, id: Int32, fromId: Int64, chatId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) + case updateShortMessage(flags: Int32, id: Int32, userId: Int64, message: String, pts: Int32, ptsCount: Int32, date: Int32, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) + case updateShortSentMessage(flags: Int32, id: Int32, pts: Int32, ptsCount: Int32, date: Int32, media: Api.MessageMedia?, entities: [Api.MessageEntity]?, ttlPeriod: Int32?) + case updates(updates: [Api.Update], users: [Api.User], chats: [Api.Chat], date: Int32, seq: Int32) + case updatesCombined(updates: [Api.Update], users: [Api.User], chats: [Api.Chat], date: Int32, seqStart: Int32, seq: Int32) + case updatesTooLong public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .webPageAttributeTheme(let flags, let documents, let settings): + case .updateShort(let update, let date): if boxed { - buffer.appendInt32(1421174295) + buffer.appendInt32(2027216577) + } + update.serialize(buffer, true) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .updateShortChatMessage(let flags, let id, let fromId, let chatId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): + if boxed { + buffer.appendInt32(1299050149) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(documents!.count)) - for item in documents! { + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt64(fromId, buffer: buffer, boxed: false) + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} + if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { item.serialize(buffer, true) }} - if Int(flags) & Int(1 << 1) != 0 {settings!.serialize(buffer, true)} + if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .webPageAttributeTheme(let flags, let documents, let settings): - return ("webPageAttributeTheme", [("flags", String(describing: flags)), ("documents", String(describing: documents)), ("settings", String(describing: settings))]) - } - } - - public static func parse_webPageAttributeTheme(_ reader: BufferReader) -> WebPageAttribute? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.Document]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } } - var _3: Api.ThemeSettings? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.ThemeSettings - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.WebPageAttribute.webPageAttributeTheme(flags: _1!, documents: _2, settings: _3) - } - else { - return nil - } - } - - } -} -public extension Api { - enum WebViewMessageSent: TypeConstructorDescription { - case webViewMessageSent(flags: Int32, msgId: Api.InputBotInlineMessageID?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .webViewMessageSent(let flags, let msgId): + case .updateShortMessage(let flags, let id, let userId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): if boxed { - buffer.appendInt32(211046684) + buffer.appendInt32(826001400) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {msgId!.serialize(buffer, true)} + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)} + if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .webViewMessageSent(let flags, let msgId): - return ("webViewMessageSent", [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]) - } - } - - public static func parse_webViewMessageSent(_ reader: BufferReader) -> WebViewMessageSent? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.InputBotInlineMessageID? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - if _c1 && _c2 { - return Api.WebViewMessageSent.webViewMessageSent(flags: _1!, msgId: _2) - } - else { - return nil - } - } - - } -} -public extension Api { - enum WebViewResult: TypeConstructorDescription { - case webViewResultUrl(queryId: Int64, url: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .webViewResultUrl(let queryId, let url): + case .updateShortSentMessage(let flags, let id, let pts, let ptsCount, let date, let media, let entities, let ttlPeriod): if boxed { - buffer.appendInt32(202659196) - } - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .webViewResultUrl(let queryId, let url): - return ("webViewResultUrl", [("queryId", String(describing: queryId)), ("url", String(describing: url))]) - } - } - - public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? { - var _1: Int64? - _1 = reader.readInt64() - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.WebViewResult.webViewResultUrl(queryId: _1!, url: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum AuthorizationForm: TypeConstructorDescription { - case authorizationForm(flags: Int32, requiredTypes: [Api.SecureRequiredType], values: [Api.SecureValue], errors: [Api.SecureValueError], users: [Api.User], privacyPolicyUrl: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .authorizationForm(let flags, let requiredTypes, let values, let errors, let users, let privacyPolicyUrl): - if boxed { - buffer.appendInt32(-1389486888) + buffer.appendInt32(-1877614335) } serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(requiredTypes.count)) - for item in requiredTypes { + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 9) != 0 {media!.serialize(buffer, true)} + if Int(flags) & Int(1 << 7) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 25) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} + break + case .updates(let updates, let users, let chats, let date, let seq): + if boxed { + buffer.appendInt32(1957577280) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(values.count)) - for item in values { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(errors.count)) - for item in errors { + buffer.appendInt32(Int32(updates.count)) + for item in updates { item.serialize(buffer, true) } buffer.appendInt32(481674261) @@ -163,572 +91,40 @@ public extension Api.account { for item in users { item.serialize(buffer, true) } - if Int(flags) & Int(1 << 0) != 0 {serializeString(privacyPolicyUrl!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .authorizationForm(let flags, let requiredTypes, let values, let errors, let users, let privacyPolicyUrl): - return ("authorizationForm", [("flags", String(describing: flags)), ("requiredTypes", String(describing: requiredTypes)), ("values", String(describing: values)), ("errors", String(describing: errors)), ("users", String(describing: users)), ("privacyPolicyUrl", String(describing: privacyPolicyUrl))]) - } - } - - public static func parse_authorizationForm(_ reader: BufferReader) -> AuthorizationForm? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.SecureRequiredType]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureRequiredType.self) - } - var _3: [Api.SecureValue]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) - } - var _4: [Api.SecureValueError]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValueError.self) - } - var _5: [Api.User]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _6: String? - if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.account.AuthorizationForm.authorizationForm(flags: _1!, requiredTypes: _2!, values: _3!, errors: _4!, users: _5!, privacyPolicyUrl: _6) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum Authorizations: TypeConstructorDescription { - case authorizations(authorizationTtlDays: Int32, authorizations: [Api.Authorization]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .authorizations(let authorizationTtlDays, let authorizations): - if boxed { - buffer.appendInt32(1275039392) - } - serializeInt32(authorizationTtlDays, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(authorizations.count)) - for item in authorizations { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .authorizations(let authorizationTtlDays, let authorizations): - return ("authorizations", [("authorizationTtlDays", String(describing: authorizationTtlDays)), ("authorizations", String(describing: authorizations))]) - } - } - - public static func parse_authorizations(_ reader: BufferReader) -> Authorizations? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.Authorization]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Authorization.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.account.Authorizations.authorizations(authorizationTtlDays: _1!, authorizations: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum AutoDownloadSettings: TypeConstructorDescription { - case autoDownloadSettings(low: Api.AutoDownloadSettings, medium: Api.AutoDownloadSettings, high: Api.AutoDownloadSettings) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .autoDownloadSettings(let low, let medium, let high): - if boxed { - buffer.appendInt32(1674235686) - } - low.serialize(buffer, true) - medium.serialize(buffer, true) - high.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .autoDownloadSettings(let low, let medium, let high): - return ("autoDownloadSettings", [("low", String(describing: low)), ("medium", String(describing: medium)), ("high", String(describing: high))]) - } - } - - public static func parse_autoDownloadSettings(_ reader: BufferReader) -> AutoDownloadSettings? { - var _1: Api.AutoDownloadSettings? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings - } - var _2: Api.AutoDownloadSettings? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings - } - var _3: Api.AutoDownloadSettings? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.account.AutoDownloadSettings.autoDownloadSettings(low: _1!, medium: _2!, high: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum ContentSettings: TypeConstructorDescription { - case contentSettings(flags: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .contentSettings(let flags): - if boxed { - buffer.appendInt32(1474462241) - } - serializeInt32(flags, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .contentSettings(let flags): - return ("contentSettings", [("flags", String(describing: flags))]) - } - } - - public static func parse_contentSettings(_ reader: BufferReader) -> ContentSettings? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.account.ContentSettings.contentSettings(flags: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum Password: TypeConstructorDescription { - case password(flags: Int32, currentAlgo: Api.PasswordKdfAlgo?, srpB: Buffer?, srpId: Int64?, hint: String?, emailUnconfirmedPattern: String?, newAlgo: Api.PasswordKdfAlgo, newSecureAlgo: Api.SecurePasswordKdfAlgo, secureRandom: Buffer, pendingResetDate: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .password(let flags, let currentAlgo, let srpB, let srpId, let hint, let emailUnconfirmedPattern, let newAlgo, let newSecureAlgo, let secureRandom, let pendingResetDate): - if boxed { - buffer.appendInt32(408623183) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {currentAlgo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeBytes(srpB!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt64(srpId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(hint!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(emailUnconfirmedPattern!, buffer: buffer, boxed: false)} - newAlgo.serialize(buffer, true) - newSecureAlgo.serialize(buffer, true) - serializeBytes(secureRandom, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 5) != 0 {serializeInt32(pendingResetDate!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .password(let flags, let currentAlgo, let srpB, let srpId, let hint, let emailUnconfirmedPattern, let newAlgo, let newSecureAlgo, let secureRandom, let pendingResetDate): - return ("password", [("flags", String(describing: flags)), ("currentAlgo", String(describing: currentAlgo)), ("srpB", String(describing: srpB)), ("srpId", String(describing: srpId)), ("hint", String(describing: hint)), ("emailUnconfirmedPattern", String(describing: emailUnconfirmedPattern)), ("newAlgo", String(describing: newAlgo)), ("newSecureAlgo", String(describing: newSecureAlgo)), ("secureRandom", String(describing: secureRandom)), ("pendingResetDate", String(describing: pendingResetDate))]) - } - } - - public static func parse_password(_ reader: BufferReader) -> Password? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.PasswordKdfAlgo? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo - } } - var _3: Buffer? - if Int(_1!) & Int(1 << 2) != 0 {_3 = parseBytes(reader) } - var _4: Int64? - if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt64() } - var _5: String? - if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) } - var _6: String? - if Int(_1!) & Int(1 << 4) != 0 {_6 = parseString(reader) } - var _7: Api.PasswordKdfAlgo? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo - } - var _8: Api.SecurePasswordKdfAlgo? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.SecurePasswordKdfAlgo - } - var _9: Buffer? - _9 = parseBytes(reader) - var _10: Int32? - if Int(_1!) & Int(1 << 5) != 0 {_10 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = (Int(_1!) & Int(1 << 5) == 0) || _10 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { - return Api.account.Password.password(flags: _1!, currentAlgo: _2, srpB: _3, srpId: _4, hint: _5, emailUnconfirmedPattern: _6, newAlgo: _7!, newSecureAlgo: _8!, secureRandom: _9!, pendingResetDate: _10) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum PasswordInputSettings: TypeConstructorDescription { - case passwordInputSettings(flags: Int32, newAlgo: Api.PasswordKdfAlgo?, newPasswordHash: Buffer?, hint: String?, email: String?, newSecureSettings: Api.SecureSecretSettings?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .passwordInputSettings(let flags, let newAlgo, let newPasswordHash, let hint, let email, let newSecureSettings): - if boxed { - buffer.appendInt32(-1036572727) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {newAlgo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(newPasswordHash!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeString(hint!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(email!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {newSecureSettings!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .passwordInputSettings(let flags, let newAlgo, let newPasswordHash, let hint, let email, let newSecureSettings): - return ("passwordInputSettings", [("flags", String(describing: flags)), ("newAlgo", String(describing: newAlgo)), ("newPasswordHash", String(describing: newPasswordHash)), ("hint", String(describing: hint)), ("email", String(describing: email)), ("newSecureSettings", String(describing: newSecureSettings))]) - } - } - - public static func parse_passwordInputSettings(_ reader: BufferReader) -> PasswordInputSettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.PasswordKdfAlgo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo - } } - var _3: Buffer? - if Int(_1!) & Int(1 << 0) != 0 {_3 = parseBytes(reader) } - var _4: String? - if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } - var _5: String? - if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) } - var _6: Api.SecureSecretSettings? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.SecureSecretSettings - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.account.PasswordInputSettings.passwordInputSettings(flags: _1!, newAlgo: _2, newPasswordHash: _3, hint: _4, email: _5, newSecureSettings: _6) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum PasswordSettings: TypeConstructorDescription { - case passwordSettings(flags: Int32, email: String?, secureSettings: Api.SecureSecretSettings?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .passwordSettings(let flags, let email, let secureSettings): - if boxed { - buffer.appendInt32(-1705233435) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(email!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {secureSettings!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .passwordSettings(let flags, let email, let secureSettings): - return ("passwordSettings", [("flags", String(describing: flags)), ("email", String(describing: email)), ("secureSettings", String(describing: secureSettings))]) - } - } - - public static func parse_passwordSettings(_ reader: BufferReader) -> PasswordSettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } - var _3: Api.SecureSecretSettings? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.SecureSecretSettings - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.account.PasswordSettings.passwordSettings(flags: _1!, email: _2, secureSettings: _3) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum PrivacyRules: TypeConstructorDescription { - case privacyRules(rules: [Api.PrivacyRule], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .privacyRules(let rules, let chats, let users): - if boxed { - buffer.appendInt32(1352683077) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rules.count)) - for item in rules { - item.serialize(buffer, true) - } buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) for item in chats { item.serialize(buffer, true) } + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(seq, buffer: buffer, boxed: false) + break + case .updatesCombined(let updates, let users, let chats, let date, let seqStart, let seq): + if boxed { + buffer.appendInt32(1918567619) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(updates.count)) + for item in updates { + 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 .privacyRules(let rules, let chats, let users): - return ("privacyRules", [("rules", String(describing: rules)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_privacyRules(_ reader: BufferReader) -> PrivacyRules? { - var _1: [Api.PrivacyRule]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.account.PrivacyRules.privacyRules(rules: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum ResetPasswordResult: TypeConstructorDescription { - case resetPasswordFailedWait(retryDate: Int32) - case resetPasswordOk - case resetPasswordRequestedWait(untilDate: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .resetPasswordFailedWait(let retryDate): - if boxed { - buffer.appendInt32(-478701471) - } - serializeInt32(retryDate, buffer: buffer, boxed: false) - break - case .resetPasswordOk: - if boxed { - buffer.appendInt32(-383330754) - } - - break - case .resetPasswordRequestedWait(let untilDate): - if boxed { - buffer.appendInt32(-370148227) - } - serializeInt32(untilDate, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .resetPasswordFailedWait(let retryDate): - return ("resetPasswordFailedWait", [("retryDate", String(describing: retryDate))]) - case .resetPasswordOk: - return ("resetPasswordOk", []) - case .resetPasswordRequestedWait(let untilDate): - return ("resetPasswordRequestedWait", [("untilDate", String(describing: untilDate))]) - } - } - - public static func parse_resetPasswordFailedWait(_ reader: BufferReader) -> ResetPasswordResult? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.account.ResetPasswordResult.resetPasswordFailedWait(retryDate: _1!) - } - else { - return nil - } - } - public static func parse_resetPasswordOk(_ reader: BufferReader) -> ResetPasswordResult? { - return Api.account.ResetPasswordResult.resetPasswordOk - } - public static func parse_resetPasswordRequestedWait(_ reader: BufferReader) -> ResetPasswordResult? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.account.ResetPasswordResult.resetPasswordRequestedWait(untilDate: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum SavedRingtone: TypeConstructorDescription { - case savedRingtone - case savedRingtoneConverted(document: Api.Document) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .savedRingtone: - if boxed { - buffer.appendInt32(-1222230163) - } - - break - case .savedRingtoneConverted(let document): - if boxed { - buffer.appendInt32(523271863) - } - document.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .savedRingtone: - return ("savedRingtone", []) - case .savedRingtoneConverted(let document): - return ("savedRingtoneConverted", [("document", String(describing: document))]) - } - } - - public static func parse_savedRingtone(_ reader: BufferReader) -> SavedRingtone? { - return Api.account.SavedRingtone.savedRingtone - } - public static func parse_savedRingtoneConverted(_ reader: BufferReader) -> SavedRingtone? { - var _1: Api.Document? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Document - } - let _c1 = _1 != nil - if _c1 { - return Api.account.SavedRingtone.savedRingtoneConverted(document: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.account { - enum SavedRingtones: TypeConstructorDescription { - case savedRingtones(hash: Int64, ringtones: [Api.Document]) - case savedRingtonesNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .savedRingtones(let hash, let ringtones): - if boxed { - buffer.appendInt32(-1041683259) - } - serializeInt64(hash, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(ringtones.count)) - for item in ringtones { + buffer.appendInt32(Int32(chats.count)) + for item in chats { item.serialize(buffer, true) } + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(seqStart, buffer: buffer, boxed: false) + serializeInt32(seq, buffer: buffer, boxed: false) break - case .savedRingtonesNotModified: + case .updatesTooLong: if boxed { - buffer.appendInt32(-67704655) + buffer.appendInt32(-484987010) } break @@ -737,67 +133,315 @@ public extension Api.account { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .savedRingtones(let hash, let ringtones): - return ("savedRingtones", [("hash", String(describing: hash)), ("ringtones", String(describing: ringtones))]) - case .savedRingtonesNotModified: - return ("savedRingtonesNotModified", []) + case .updateShort(let update, let date): + return ("updateShort", [("update", String(describing: update)), ("date", String(describing: date))]) + case .updateShortChatMessage(let flags, let id, let fromId, let chatId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): + return ("updateShortChatMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("fromId", String(describing: fromId)), ("chatId", String(describing: chatId)), ("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) + case .updateShortMessage(let flags, let id, let userId, let message, let pts, let ptsCount, let date, let fwdFrom, let viaBotId, let replyTo, let entities, let ttlPeriod): + return ("updateShortMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("message", String(describing: message)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("fwdFrom", String(describing: fwdFrom)), ("viaBotId", String(describing: viaBotId)), ("replyTo", String(describing: replyTo)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) + case .updateShortSentMessage(let flags, let id, let pts, let ptsCount, let date, let media, let entities, let ttlPeriod): + return ("updateShortSentMessage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("date", String(describing: date)), ("media", String(describing: media)), ("entities", String(describing: entities)), ("ttlPeriod", String(describing: ttlPeriod))]) + case .updates(let updates, let users, let chats, let date, let seq): + return ("updates", [("updates", String(describing: updates)), ("users", String(describing: users)), ("chats", String(describing: chats)), ("date", String(describing: date)), ("seq", String(describing: seq))]) + case .updatesCombined(let updates, let users, let chats, let date, let seqStart, let seq): + return ("updatesCombined", [("updates", String(describing: updates)), ("users", String(describing: users)), ("chats", String(describing: chats)), ("date", String(describing: date)), ("seqStart", String(describing: seqStart)), ("seq", String(describing: seq))]) + case .updatesTooLong: + return ("updatesTooLong", []) } } - public static func parse_savedRingtones(_ reader: BufferReader) -> SavedRingtones? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.Document]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + public static func parse_updateShort(_ reader: BufferReader) -> Updates? { + var _1: Api.Update? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Update } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.account.SavedRingtones.savedRingtones(hash: _1!, ringtones: _2!) - } - else { - return nil - } - } - public static func parse_savedRingtonesNotModified(_ reader: BufferReader) -> SavedRingtones? { - return Api.account.SavedRingtones.savedRingtonesNotModified - } - - } -} -public extension Api.account { - enum SentEmailCode: TypeConstructorDescription { - case sentEmailCode(emailPattern: String, length: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sentEmailCode(let emailPattern, let length): - if boxed { - buffer.appendInt32(-2128640689) - } - serializeString(emailPattern, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .sentEmailCode(let emailPattern, let length): - return ("sentEmailCode", [("emailPattern", String(describing: emailPattern)), ("length", String(describing: length))]) - } - } - - public static func parse_sentEmailCode(_ reader: BufferReader) -> SentEmailCode? { - var _1: String? - _1 = parseString(reader) var _2: Int32? _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.account.SentEmailCode.sentEmailCode(emailPattern: _1!, length: _2!) + return Api.Updates.updateShort(update: _1!, date: _2!) + } + else { + return nil + } + } + public static func parse_updateShortChatMessage(_ reader: BufferReader) -> Updates? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int64? + _4 = reader.readInt64() + var _5: String? + _5 = parseString(reader) + var _6: Int32? + _6 = reader.readInt32() + var _7: Int32? + _7 = reader.readInt32() + var _8: Int32? + _8 = reader.readInt32() + var _9: Api.MessageFwdHeader? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader + } } + var _10: Int64? + if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt64() } + var _11: Api.MessageReplyHeader? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader + } } + var _12: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { + _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + var _13: Int32? + if Int(_1!) & Int(1 << 25) != 0 {_13 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = (Int(_1!) & Int(1 << 2) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 3) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 25) == 0) || _13 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { + return Api.Updates.updateShortChatMessage(flags: _1!, id: _2!, fromId: _3!, chatId: _4!, message: _5!, pts: _6!, ptsCount: _7!, date: _8!, fwdFrom: _9, viaBotId: _10, replyTo: _11, entities: _12, ttlPeriod: _13) + } + else { + return nil + } + } + public static func parse_updateShortMessage(_ reader: BufferReader) -> Updates? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + var _7: Int32? + _7 = reader.readInt32() + var _8: Api.MessageFwdHeader? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader + } } + var _9: Int64? + if Int(_1!) & Int(1 << 11) != 0 {_9 = reader.readInt64() } + var _10: Api.MessageReplyHeader? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader + } } + var _11: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { + _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + var _12: Int32? + if Int(_1!) & Int(1 << 25) != 0 {_12 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 11) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 3) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 25) == 0) || _12 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 { + return Api.Updates.updateShortMessage(flags: _1!, id: _2!, userId: _3!, message: _4!, pts: _5!, ptsCount: _6!, date: _7!, fwdFrom: _8, viaBotId: _9, replyTo: _10, entities: _11, ttlPeriod: _12) + } + else { + return nil + } + } + public static func parse_updateShortSentMessage(_ reader: BufferReader) -> Updates? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Api.MessageMedia? + if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.MessageMedia + } } + var _7: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + var _8: Int32? + if Int(_1!) & Int(1 << 25) != 0 {_8 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 9) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 7) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 25) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.Updates.updateShortSentMessage(flags: _1!, id: _2!, pts: _3!, ptsCount: _4!, date: _5!, media: _6, entities: _7, ttlPeriod: _8) + } + else { + return nil + } + } + public static func parse_updates(_ reader: BufferReader) -> Updates? { + var _1: [Api.Update]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.Updates.updates(updates: _1!, users: _2!, chats: _3!, date: _4!, seq: _5!) + } + else { + return nil + } + } + public static func parse_updatesCombined(_ reader: BufferReader) -> Updates? { + var _1: [Api.Update]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Updates.updatesCombined(updates: _1!, users: _2!, chats: _3!, date: _4!, seqStart: _5!, seq: _6!) + } + else { + return nil + } + } + public static func parse_updatesTooLong(_ reader: BufferReader) -> Updates? { + return Api.Updates.updatesTooLong + } + + } +} +public extension Api { + enum UrlAuthResult: TypeConstructorDescription { + case urlAuthResultAccepted(url: String) + case urlAuthResultDefault + case urlAuthResultRequest(flags: Int32, bot: Api.User, domain: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .urlAuthResultAccepted(let url): + if boxed { + buffer.appendInt32(-1886646706) + } + serializeString(url, buffer: buffer, boxed: false) + break + case .urlAuthResultDefault: + if boxed { + buffer.appendInt32(-1445536993) + } + + break + case .urlAuthResultRequest(let flags, let bot, let domain): + if boxed { + buffer.appendInt32(-1831650802) + } + serializeInt32(flags, buffer: buffer, boxed: false) + bot.serialize(buffer, true) + serializeString(domain, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .urlAuthResultAccepted(let url): + return ("urlAuthResultAccepted", [("url", String(describing: url))]) + case .urlAuthResultDefault: + return ("urlAuthResultDefault", []) + case .urlAuthResultRequest(let flags, let bot, let domain): + return ("urlAuthResultRequest", [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("domain", String(describing: domain))]) + } + } + + public static func parse_urlAuthResultAccepted(_ reader: BufferReader) -> UrlAuthResult? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.UrlAuthResult.urlAuthResultAccepted(url: _1!) + } + else { + return nil + } + } + public static func parse_urlAuthResultDefault(_ reader: BufferReader) -> UrlAuthResult? { + return Api.UrlAuthResult.urlAuthResultDefault + } + public static func parse_urlAuthResultRequest(_ reader: BufferReader) -> UrlAuthResult? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.User? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.User + } + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.UrlAuthResult.urlAuthResultRequest(flags: _1!, bot: _2!, domain: _3!) } else { return nil @@ -806,15 +450,38 @@ public extension Api.account { } } -public extension Api.account { - enum Takeout: TypeConstructorDescription { - case takeout(id: Int64) +public extension Api { + enum User: TypeConstructorDescription { + case user(flags: Int32, id: Int64, accessHash: Int64?, firstName: String?, lastName: String?, username: String?, phone: String?, photo: Api.UserProfilePhoto?, status: Api.UserStatus?, botInfoVersion: Int32?, restrictionReason: [Api.RestrictionReason]?, botInlinePlaceholder: String?, langCode: String?) + case userEmpty(id: Int64) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .takeout(let id): + case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode): if boxed { - buffer.appendInt32(1304052993) + buffer.appendInt32(1073147056) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt64(accessHash!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(firstName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(lastName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(username!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeString(phone!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {status!.serialize(buffer, true)} + if Int(flags) & Int(1 << 14) != 0 {serializeInt32(botInfoVersion!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 18) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(restrictionReason!.count)) + for item in restrictionReason! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 19) != 0 {serializeString(botInlinePlaceholder!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 22) != 0 {serializeString(langCode!, buffer: buffer, boxed: false)} + break + case .userEmpty(let id): + if boxed { + buffer.appendInt32(-742634630) } serializeInt64(id, buffer: buffer, boxed: false) break @@ -823,17 +490,72 @@ public extension Api.account { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .takeout(let id): - return ("takeout", [("id", String(describing: id))]) + case .user(let flags, let id, let accessHash, let firstName, let lastName, let username, let phone, let photo, let status, let botInfoVersion, let restrictionReason, let botInlinePlaceholder, let langCode): + return ("user", [("flags", String(describing: flags)), ("id", String(describing: id)), ("accessHash", String(describing: accessHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("username", String(describing: username)), ("phone", String(describing: phone)), ("photo", String(describing: photo)), ("status", String(describing: status)), ("botInfoVersion", String(describing: botInfoVersion)), ("restrictionReason", String(describing: restrictionReason)), ("botInlinePlaceholder", String(describing: botInlinePlaceholder)), ("langCode", String(describing: langCode))]) + case .userEmpty(let id): + return ("userEmpty", [("id", String(describing: id))]) } } - public static func parse_takeout(_ reader: BufferReader) -> Takeout? { + public static func parse_user(_ reader: BufferReader) -> User? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt64() } + var _4: String? + if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } + var _5: String? + if Int(_1!) & Int(1 << 2) != 0 {_5 = parseString(reader) } + var _6: String? + if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) } + var _7: String? + if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) } + var _8: Api.UserProfilePhoto? + if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.UserProfilePhoto + } } + var _9: Api.UserStatus? + if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.UserStatus + } } + var _10: Int32? + if Int(_1!) & Int(1 << 14) != 0 {_10 = reader.readInt32() } + var _11: [Api.RestrictionReason]? + if Int(_1!) & Int(1 << 18) != 0 {if let _ = reader.readInt32() { + _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) + } } + var _12: String? + if Int(_1!) & Int(1 << 19) != 0 {_12 = parseString(reader) } + var _13: String? + if Int(_1!) & Int(1 << 22) != 0 {_13 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 18) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 19) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 22) == 0) || _13 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { + return Api.User.user(flags: _1!, id: _2!, accessHash: _3, firstName: _4, lastName: _5, username: _6, phone: _7, photo: _8, status: _9, botInfoVersion: _10, restrictionReason: _11, botInlinePlaceholder: _12, langCode: _13) + } + else { + return nil + } + } + public static func parse_userEmpty(_ reader: BufferReader) -> User? { var _1: Int64? _1 = reader.readInt64() let _c1 = _1 != nil if _c1 { - return Api.account.Takeout.takeout(id: _1!) + return Api.User.userEmpty(id: _1!) } else { return nil @@ -842,27 +564,139 @@ public extension Api.account { } } -public extension Api.account { - enum Themes: TypeConstructorDescription { - case themes(hash: Int64, themes: [Api.Theme]) - case themesNotModified +public extension Api { + enum UserFull: TypeConstructorDescription { + case userFull(flags: Int32, id: Int64, about: String?, settings: Api.PeerSettings, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?, premiumGifts: [Api.PremiumGiftOption]?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .themes(let hash, let themes): + case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts): if boxed { - buffer.appendInt32(-1707242387) + buffer.appendInt32(-994968513) } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(themes.count)) - for item in themes { + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeString(about!, buffer: buffer, boxed: false)} + settings.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {profilePhoto!.serialize(buffer, true)} + notifySettings.serialize(buffer, true) + if Int(flags) & Int(1 << 3) != 0 {botInfo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} + serializeInt32(commonChatsCount, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 14) != 0 {serializeInt32(ttlPeriod!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 15) != 0 {serializeString(themeEmoticon!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 16) != 0 {serializeString(privateForwardName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 17) != 0 {botGroupAdminRights!.serialize(buffer, true)} + if Int(flags) & Int(1 << 18) != 0 {botBroadcastAdminRights!.serialize(buffer, true)} + if Int(flags) & Int(1 << 19) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(premiumGifts!.count)) + for item in premiumGifts! { item.serialize(buffer, true) - } + }} break - case .themesNotModified: + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .userFull(let flags, let id, let about, let settings, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let premiumGifts): + return ("userFull", [("flags", String(describing: flags)), ("id", String(describing: id)), ("about", String(describing: about)), ("settings", String(describing: settings)), ("profilePhoto", String(describing: profilePhoto)), ("notifySettings", String(describing: notifySettings)), ("botInfo", String(describing: botInfo)), ("pinnedMsgId", String(describing: pinnedMsgId)), ("commonChatsCount", String(describing: commonChatsCount)), ("folderId", String(describing: folderId)), ("ttlPeriod", String(describing: ttlPeriod)), ("themeEmoticon", String(describing: themeEmoticon)), ("privateForwardName", String(describing: privateForwardName)), ("botGroupAdminRights", String(describing: botGroupAdminRights)), ("botBroadcastAdminRights", String(describing: botBroadcastAdminRights)), ("premiumGifts", String(describing: premiumGifts))]) + } + } + + public static func parse_userFull(_ reader: BufferReader) -> UserFull? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } + var _4: Api.PeerSettings? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.PeerSettings + } + var _5: Api.Photo? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.Photo + } } + var _6: Api.PeerNotifySettings? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings + } + var _7: Api.BotInfo? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.BotInfo + } } + var _8: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_8 = reader.readInt32() } + var _9: Int32? + _9 = reader.readInt32() + var _10: Int32? + if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt32() } + var _11: Int32? + if Int(_1!) & Int(1 << 14) != 0 {_11 = reader.readInt32() } + var _12: String? + if Int(_1!) & Int(1 << 15) != 0 {_12 = parseString(reader) } + var _13: String? + if Int(_1!) & Int(1 << 16) != 0 {_13 = parseString(reader) } + var _14: Api.ChatAdminRights? + if Int(_1!) & Int(1 << 17) != 0 {if let signature = reader.readInt32() { + _14 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights + } } + var _15: Api.ChatAdminRights? + if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { + _15 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights + } } + var _16: [Api.PremiumGiftOption]? + if Int(_1!) & Int(1 << 19) != 0 {if let _ = reader.readInt32() { + _16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PremiumGiftOption.self) + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 6) == 0) || _8 != nil + let _c9 = _9 != nil + let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 14) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 15) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 16) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 17) == 0) || _14 != nil + let _c15 = (Int(_1!) & Int(1 << 18) == 0) || _15 != nil + let _c16 = (Int(_1!) & Int(1 << 19) == 0) || _16 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 { + return Api.UserFull.userFull(flags: _1!, id: _2!, about: _3, settings: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!, folderId: _10, ttlPeriod: _11, themeEmoticon: _12, privateForwardName: _13, botGroupAdminRights: _14, botBroadcastAdminRights: _15, premiumGifts: _16) + } + else { + return nil + } + } + + } +} +public extension Api { + enum UserProfilePhoto: TypeConstructorDescription { + case userProfilePhoto(flags: Int32, photoId: Int64, strippedThumb: Buffer?, dcId: Int32) + case userProfilePhotoEmpty + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .userProfilePhoto(let flags, let photoId, let strippedThumb, let dcId): if boxed { - buffer.appendInt32(-199313886) + buffer.appendInt32(-2100168954) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(photoId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeBytes(strippedThumb!, buffer: buffer, boxed: false)} + serializeInt32(dcId, buffer: buffer, boxed: false) + break + case .userProfilePhotoEmpty: + if boxed { + buffer.appendInt32(1326562017) } break @@ -871,67 +705,693 @@ public extension Api.account { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .themes(let hash, let themes): - return ("themes", [("hash", String(describing: hash)), ("themes", String(describing: themes))]) - case .themesNotModified: - return ("themesNotModified", []) + case .userProfilePhoto(let flags, let photoId, let strippedThumb, let dcId): + return ("userProfilePhoto", [("flags", String(describing: flags)), ("photoId", String(describing: photoId)), ("strippedThumb", String(describing: strippedThumb)), ("dcId", String(describing: dcId))]) + case .userProfilePhotoEmpty: + return ("userProfilePhotoEmpty", []) } } - public static func parse_themes(_ reader: BufferReader) -> Themes? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.Theme]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Theme.self) - } + public static func parse_userProfilePhoto(_ reader: BufferReader) -> UserProfilePhoto? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Buffer? + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseBytes(reader) } + var _4: Int32? + _4 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.account.Themes.themes(hash: _1!, themes: _2!) + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.UserProfilePhoto.userProfilePhoto(flags: _1!, photoId: _2!, strippedThumb: _3, dcId: _4!) } else { return nil } } - public static func parse_themesNotModified(_ reader: BufferReader) -> Themes? { - return Api.account.Themes.themesNotModified + public static func parse_userProfilePhotoEmpty(_ reader: BufferReader) -> UserProfilePhoto? { + return Api.UserProfilePhoto.userProfilePhotoEmpty } } } -public extension Api.account { - enum TmpPassword: TypeConstructorDescription { - case tmpPassword(tmpPassword: Buffer, validUntil: Int32) +public extension Api { + enum UserStatus: TypeConstructorDescription { + case userStatusEmpty + case userStatusLastMonth + case userStatusLastWeek + case userStatusOffline(wasOnline: Int32) + case userStatusOnline(expires: Int32) + case userStatusRecently public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .tmpPassword(let tmpPassword, let validUntil): + case .userStatusEmpty: if boxed { - buffer.appendInt32(-614138572) + buffer.appendInt32(164646985) } - serializeBytes(tmpPassword, buffer: buffer, boxed: false) - serializeInt32(validUntil, buffer: buffer, boxed: false) + + break + case .userStatusLastMonth: + if boxed { + buffer.appendInt32(2011940674) + } + + break + case .userStatusLastWeek: + if boxed { + buffer.appendInt32(129960444) + } + + break + case .userStatusOffline(let wasOnline): + if boxed { + buffer.appendInt32(9203775) + } + serializeInt32(wasOnline, buffer: buffer, boxed: false) + break + case .userStatusOnline(let expires): + if boxed { + buffer.appendInt32(-306628279) + } + serializeInt32(expires, buffer: buffer, boxed: false) + break + case .userStatusRecently: + if boxed { + buffer.appendInt32(-496024847) + } + break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .tmpPassword(let tmpPassword, let validUntil): - return ("tmpPassword", [("tmpPassword", String(describing: tmpPassword)), ("validUntil", String(describing: validUntil))]) + case .userStatusEmpty: + return ("userStatusEmpty", []) + case .userStatusLastMonth: + return ("userStatusLastMonth", []) + case .userStatusLastWeek: + return ("userStatusLastWeek", []) + case .userStatusOffline(let wasOnline): + return ("userStatusOffline", [("wasOnline", String(describing: wasOnline))]) + case .userStatusOnline(let expires): + return ("userStatusOnline", [("expires", String(describing: expires))]) + case .userStatusRecently: + return ("userStatusRecently", []) } } - public static func parse_tmpPassword(_ reader: BufferReader) -> TmpPassword? { - var _1: Buffer? - _1 = parseBytes(reader) + public static func parse_userStatusEmpty(_ reader: BufferReader) -> UserStatus? { + return Api.UserStatus.userStatusEmpty + } + public static func parse_userStatusLastMonth(_ reader: BufferReader) -> UserStatus? { + return Api.UserStatus.userStatusLastMonth + } + public static func parse_userStatusLastWeek(_ reader: BufferReader) -> UserStatus? { + return Api.UserStatus.userStatusLastWeek + } + public static func parse_userStatusOffline(_ reader: BufferReader) -> UserStatus? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.UserStatus.userStatusOffline(wasOnline: _1!) + } + else { + return nil + } + } + public static func parse_userStatusOnline(_ reader: BufferReader) -> UserStatus? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.UserStatus.userStatusOnline(expires: _1!) + } + else { + return nil + } + } + public static func parse_userStatusRecently(_ reader: BufferReader) -> UserStatus? { + return Api.UserStatus.userStatusRecently + } + + } +} +public extension Api { + enum VideoSize: TypeConstructorDescription { + case videoSize(flags: Int32, type: String, w: Int32, h: Int32, size: Int32, videoStartTs: Double?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .videoSize(let flags, let type, let w, let h, let size, let videoStartTs): + if boxed { + buffer.appendInt32(-567037804) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(type, buffer: buffer, boxed: false) + serializeInt32(w, buffer: buffer, boxed: false) + serializeInt32(h, buffer: buffer, boxed: false) + serializeInt32(size, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .videoSize(let flags, let type, let w, let h, let size, let videoStartTs): + return ("videoSize", [("flags", String(describing: flags)), ("type", String(describing: type)), ("w", String(describing: w)), ("h", String(describing: h)), ("size", String(describing: size)), ("videoStartTs", String(describing: videoStartTs))]) + } + } + + public static func parse_videoSize(_ reader: BufferReader) -> VideoSize? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Double? + if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readDouble() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.VideoSize.videoSize(flags: _1!, type: _2!, w: _3!, h: _4!, size: _5!, videoStartTs: _6) + } + else { + return nil + } + } + + } +} +public extension Api { + enum WallPaper: TypeConstructorDescription { + case wallPaper(id: Int64, flags: Int32, accessHash: Int64, slug: String, document: Api.Document, settings: Api.WallPaperSettings?) + case wallPaperNoFile(id: Int64, flags: Int32, settings: Api.WallPaperSettings?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .wallPaper(let id, let flags, let accessHash, let slug, let document, let settings): + if boxed { + buffer.appendInt32(-1539849235) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeString(slug, buffer: buffer, boxed: false) + document.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {settings!.serialize(buffer, true)} + break + case .wallPaperNoFile(let id, let flags, let settings): + if boxed { + buffer.appendInt32(-528465642) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {settings!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .wallPaper(let id, let flags, let accessHash, let slug, let document, let settings): + return ("wallPaper", [("id", String(describing: id)), ("flags", String(describing: flags)), ("accessHash", String(describing: accessHash)), ("slug", String(describing: slug)), ("document", String(describing: document)), ("settings", String(describing: settings))]) + case .wallPaperNoFile(let id, let flags, let settings): + return ("wallPaperNoFile", [("id", String(describing: id)), ("flags", String(describing: flags)), ("settings", String(describing: settings))]) + } + } + + public static func parse_wallPaper(_ reader: BufferReader) -> WallPaper? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: Api.Document? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.Document + } + var _6: Api.WallPaperSettings? + if Int(_2!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_2!) & Int(1 << 2) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.WallPaper.wallPaper(id: _1!, flags: _2!, accessHash: _3!, slug: _4!, document: _5!, settings: _6) + } + else { + return nil + } + } + public static func parse_wallPaperNoFile(_ reader: BufferReader) -> WallPaper? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.WallPaperSettings? + if Int(_2!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_2!) & Int(1 << 2) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.WallPaper.wallPaperNoFile(id: _1!, flags: _2!, settings: _3) + } + else { + return nil + } + } + + } +} +public extension Api { + enum WallPaperSettings: TypeConstructorDescription { + case wallPaperSettings(flags: Int32, backgroundColor: Int32?, secondBackgroundColor: Int32?, thirdBackgroundColor: Int32?, fourthBackgroundColor: Int32?, intensity: Int32?, rotation: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .wallPaperSettings(let flags, let backgroundColor, let secondBackgroundColor, let thirdBackgroundColor, let fourthBackgroundColor, let intensity, let rotation): + if boxed { + buffer.appendInt32(499236004) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(backgroundColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(secondBackgroundColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {serializeInt32(thirdBackgroundColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(fourthBackgroundColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(intensity!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeInt32(rotation!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .wallPaperSettings(let flags, let backgroundColor, let secondBackgroundColor, let thirdBackgroundColor, let fourthBackgroundColor, let intensity, let rotation): + return ("wallPaperSettings", [("flags", String(describing: flags)), ("backgroundColor", String(describing: backgroundColor)), ("secondBackgroundColor", String(describing: secondBackgroundColor)), ("thirdBackgroundColor", String(describing: thirdBackgroundColor)), ("fourthBackgroundColor", String(describing: fourthBackgroundColor)), ("intensity", String(describing: intensity)), ("rotation", String(describing: rotation))]) + } + } + + public static func parse_wallPaperSettings(_ reader: BufferReader) -> WallPaperSettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Int32? + if Int(_1!) & Int(1 << 4) != 0 {_3 = reader.readInt32() } + var _4: Int32? + if Int(_1!) & Int(1 << 5) != 0 {_4 = reader.readInt32() } + var _5: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_5 = reader.readInt32() } + var _6: Int32? + if Int(_1!) & Int(1 << 3) != 0 {_6 = reader.readInt32() } + var _7: Int32? + if Int(_1!) & Int(1 << 4) != 0 {_7 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 4) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 5) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 6) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.WallPaperSettings.wallPaperSettings(flags: _1!, backgroundColor: _2, secondBackgroundColor: _3, thirdBackgroundColor: _4, fourthBackgroundColor: _5, intensity: _6, rotation: _7) + } + else { + return nil + } + } + + } +} +public extension Api { + enum WebAuthorization: TypeConstructorDescription { + case webAuthorization(hash: Int64, botId: Int64, domain: String, browser: String, platform: String, dateCreated: Int32, dateActive: Int32, ip: String, region: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .webAuthorization(let hash, let botId, let domain, let browser, let platform, let dateCreated, let dateActive, let ip, let region): + if boxed { + buffer.appendInt32(-1493633966) + } + serializeInt64(hash, buffer: buffer, boxed: false) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeString(domain, buffer: buffer, boxed: false) + serializeString(browser, buffer: buffer, boxed: false) + serializeString(platform, buffer: buffer, boxed: false) + serializeInt32(dateCreated, buffer: buffer, boxed: false) + serializeInt32(dateActive, buffer: buffer, boxed: false) + serializeString(ip, buffer: buffer, boxed: false) + serializeString(region, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .webAuthorization(let hash, let botId, let domain, let browser, let platform, let dateCreated, let dateActive, let ip, let region): + return ("webAuthorization", [("hash", String(describing: hash)), ("botId", String(describing: botId)), ("domain", String(describing: domain)), ("browser", String(describing: browser)), ("platform", String(describing: platform)), ("dateCreated", String(describing: dateCreated)), ("dateActive", String(describing: dateActive)), ("ip", String(describing: ip)), ("region", String(describing: region))]) + } + } + + public static func parse_webAuthorization(_ reader: BufferReader) -> WebAuthorization? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: Int32? + _6 = reader.readInt32() + var _7: Int32? + _7 = reader.readInt32() + var _8: String? + _8 = parseString(reader) + var _9: String? + _9 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.WebAuthorization.webAuthorization(hash: _1!, botId: _2!, domain: _3!, browser: _4!, platform: _5!, dateCreated: _6!, dateActive: _7!, ip: _8!, region: _9!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum WebDocument: TypeConstructorDescription { + case webDocument(url: String, accessHash: Int64, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) + case webDocumentNoProxy(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .webDocument(let url, let accessHash, let size, let mimeType, let attributes): + if boxed { + buffer.appendInt32(475467473) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeInt32(size, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(attributes.count)) + for item in attributes { + item.serialize(buffer, true) + } + break + case .webDocumentNoProxy(let url, let size, let mimeType, let attributes): + if boxed { + buffer.appendInt32(-104284986) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt32(size, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(attributes.count)) + for item in attributes { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .webDocument(let url, let accessHash, let size, let mimeType, let attributes): + return ("webDocument", [("url", String(describing: url)), ("accessHash", String(describing: accessHash)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) + case .webDocumentNoProxy(let url, let size, let mimeType, let attributes): + return ("webDocumentNoProxy", [("url", String(describing: url)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) + } + } + + public static func parse_webDocument(_ reader: BufferReader) -> WebDocument? { + var _1: String? + _1 = parseString(reader) + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: String? + _4 = parseString(reader) + var _5: [Api.DocumentAttribute]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.WebDocument.webDocument(url: _1!, accessHash: _2!, size: _3!, mimeType: _4!, attributes: _5!) + } + else { + return nil + } + } + public static func parse_webDocumentNoProxy(_ reader: BufferReader) -> WebDocument? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: [Api.DocumentAttribute]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.WebDocument.webDocumentNoProxy(url: _1!, size: _2!, mimeType: _3!, attributes: _4!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum WebPage: TypeConstructorDescription { + case webPage(flags: Int32, id: Int64, url: String, displayUrl: String, hash: Int32, type: String?, siteName: String?, title: String?, description: String?, photo: Api.Photo?, embedUrl: String?, embedType: String?, embedWidth: Int32?, embedHeight: Int32?, duration: Int32?, author: String?, document: Api.Document?, cachedPage: Api.Page?, attributes: [Api.WebPageAttribute]?) + case webPageEmpty(id: Int64) + case webPageNotModified(flags: Int32, cachedPageViews: Int32?) + case webPagePending(id: Int64, date: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .webPage(let flags, let id, let url, let displayUrl, let hash, let type, let siteName, let title, let description, let photo, let embedUrl, let embedType, let embedWidth, let embedHeight, let duration, let author, let document, let cachedPage, let attributes): + if boxed { + buffer.appendInt32(-392411726) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(id, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + serializeString(displayUrl, buffer: buffer, boxed: false) + serializeInt32(hash, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(type!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(siteName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(description!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {photo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 5) != 0 {serializeString(embedUrl!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 5) != 0 {serializeString(embedType!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(embedWidth!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(embedHeight!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 7) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 8) != 0 {serializeString(author!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 9) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 10) != 0 {cachedPage!.serialize(buffer, true)} + if Int(flags) & Int(1 << 12) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(attributes!.count)) + for item in attributes! { + item.serialize(buffer, true) + }} + break + case .webPageEmpty(let id): + if boxed { + buffer.appendInt32(-350980120) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + case .webPageNotModified(let flags, let cachedPageViews): + if boxed { + buffer.appendInt32(1930545681) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(cachedPageViews!, buffer: buffer, boxed: false)} + break + case .webPagePending(let id, let date): + if boxed { + buffer.appendInt32(-981018084) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .webPage(let flags, let id, let url, let displayUrl, let hash, let type, let siteName, let title, let description, let photo, let embedUrl, let embedType, let embedWidth, let embedHeight, let duration, let author, let document, let cachedPage, let attributes): + return ("webPage", [("flags", String(describing: flags)), ("id", String(describing: id)), ("url", String(describing: url)), ("displayUrl", String(describing: displayUrl)), ("hash", String(describing: hash)), ("type", String(describing: type)), ("siteName", String(describing: siteName)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("embedUrl", String(describing: embedUrl)), ("embedType", String(describing: embedType)), ("embedWidth", String(describing: embedWidth)), ("embedHeight", String(describing: embedHeight)), ("duration", String(describing: duration)), ("author", String(describing: author)), ("document", String(describing: document)), ("cachedPage", String(describing: cachedPage)), ("attributes", String(describing: attributes))]) + case .webPageEmpty(let id): + return ("webPageEmpty", [("id", String(describing: id))]) + case .webPageNotModified(let flags, let cachedPageViews): + return ("webPageNotModified", [("flags", String(describing: flags)), ("cachedPageViews", String(describing: cachedPageViews))]) + case .webPagePending(let id, let date): + return ("webPagePending", [("id", String(describing: id)), ("date", String(describing: date))]) + } + } + + public static func parse_webPage(_ reader: BufferReader) -> WebPage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: Int32? + _5 = reader.readInt32() + var _6: String? + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } + var _7: String? + if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) } + var _8: String? + if Int(_1!) & Int(1 << 2) != 0 {_8 = parseString(reader) } + var _9: String? + if Int(_1!) & Int(1 << 3) != 0 {_9 = parseString(reader) } + var _10: Api.Photo? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.Photo + } } + var _11: String? + if Int(_1!) & Int(1 << 5) != 0 {_11 = parseString(reader) } + var _12: String? + if Int(_1!) & Int(1 << 5) != 0 {_12 = parseString(reader) } + var _13: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_13 = reader.readInt32() } + var _14: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_14 = reader.readInt32() } + var _15: Int32? + if Int(_1!) & Int(1 << 7) != 0 {_15 = reader.readInt32() } + var _16: String? + if Int(_1!) & Int(1 << 8) != 0 {_16 = parseString(reader) } + var _17: Api.Document? + if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { + _17 = Api.parse(reader, signature: signature) as? Api.Document + } } + var _18: Api.Page? + if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() { + _18 = Api.parse(reader, signature: signature) as? Api.Page + } } + var _19: [Api.WebPageAttribute]? + if Int(_1!) & Int(1 << 12) != 0 {if let _ = reader.readInt32() { + _19 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WebPageAttribute.self) + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil + let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 3) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 5) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 5) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 6) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 6) == 0) || _14 != nil + let _c15 = (Int(_1!) & Int(1 << 7) == 0) || _15 != nil + let _c16 = (Int(_1!) & Int(1 << 8) == 0) || _16 != nil + let _c17 = (Int(_1!) & Int(1 << 9) == 0) || _17 != nil + let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil + let _c19 = (Int(_1!) & Int(1 << 12) == 0) || _19 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 { + return Api.WebPage.webPage(flags: _1!, id: _2!, url: _3!, displayUrl: _4!, hash: _5!, type: _6, siteName: _7, title: _8, description: _9, photo: _10, embedUrl: _11, embedType: _12, embedWidth: _13, embedHeight: _14, duration: _15, author: _16, document: _17, cachedPage: _18, attributes: _19) + } + else { + return nil + } + } + public static func parse_webPageEmpty(_ reader: BufferReader) -> WebPage? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.WebPage.webPageEmpty(id: _1!) + } + else { + return nil + } + } + public static func parse_webPageNotModified(_ reader: BufferReader) -> WebPage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + if _c1 && _c2 { + return Api.WebPage.webPageNotModified(flags: _1!, cachedPageViews: _2) + } + else { + return nil + } + } + public static func parse_webPagePending(_ reader: BufferReader) -> WebPage? { + var _1: Int64? + _1 = reader.readInt64() var _2: Int32? _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.account.TmpPassword.tmpPassword(tmpPassword: _1!, validUntil: _2!) + return Api.WebPage.webPagePending(id: _1!, date: _2!) } else { return nil @@ -940,253 +1400,3 @@ public extension Api.account { } } -public extension Api.account { - enum WallPapers: TypeConstructorDescription { - case wallPapers(hash: Int64, wallpapers: [Api.WallPaper]) - case wallPapersNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .wallPapers(let hash, let wallpapers): - if boxed { - buffer.appendInt32(-842824308) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(wallpapers.count)) - for item in wallpapers { - item.serialize(buffer, true) - } - break - case .wallPapersNotModified: - if boxed { - buffer.appendInt32(471437699) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .wallPapers(let hash, let wallpapers): - return ("wallPapers", [("hash", String(describing: hash)), ("wallpapers", String(describing: wallpapers))]) - case .wallPapersNotModified: - return ("wallPapersNotModified", []) - } - } - - public static func parse_wallPapers(_ reader: BufferReader) -> WallPapers? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.WallPaper]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WallPaper.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.account.WallPapers.wallPapers(hash: _1!, wallpapers: _2!) - } - else { - return nil - } - } - public static func parse_wallPapersNotModified(_ reader: BufferReader) -> WallPapers? { - return Api.account.WallPapers.wallPapersNotModified - } - - } -} -public extension Api.account { - enum WebAuthorizations: TypeConstructorDescription { - case webAuthorizations(authorizations: [Api.WebAuthorization], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .webAuthorizations(let authorizations, let users): - if boxed { - buffer.appendInt32(-313079300) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(authorizations.count)) - for item in authorizations { - 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 .webAuthorizations(let authorizations, let users): - return ("webAuthorizations", [("authorizations", String(describing: authorizations)), ("users", String(describing: users))]) - } - } - - public static func parse_webAuthorizations(_ reader: BufferReader) -> WebAuthorizations? { - var _1: [Api.WebAuthorization]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WebAuthorization.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.account.WebAuthorizations.webAuthorizations(authorizations: _1!, users: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.auth { - enum Authorization: TypeConstructorDescription { - case authorization(flags: Int32, otherwiseReloginDays: Int32?, tmpSessions: Int32?, user: Api.User) - case authorizationSignUpRequired(flags: Int32, termsOfService: Api.help.TermsOfService?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user): - if boxed { - buffer.appendInt32(872119224) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(otherwiseReloginDays!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)} - user.serialize(buffer, true) - break - case .authorizationSignUpRequired(let flags, let termsOfService): - if boxed { - buffer.appendInt32(1148485274) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {termsOfService!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user): - return ("authorization", [("flags", String(describing: flags)), ("otherwiseReloginDays", String(describing: otherwiseReloginDays)), ("tmpSessions", String(describing: tmpSessions)), ("user", String(describing: user))]) - case .authorizationSignUpRequired(let flags, let termsOfService): - return ("authorizationSignUpRequired", [("flags", String(describing: flags)), ("termsOfService", String(describing: termsOfService))]) - } - } - - public static func parse_authorization(_ reader: BufferReader) -> Authorization? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - var _4: Api.User? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.User - } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.auth.Authorization.authorization(flags: _1!, otherwiseReloginDays: _2, tmpSessions: _3, user: _4!) - } - else { - return nil - } - } - public static func parse_authorizationSignUpRequired(_ reader: BufferReader) -> Authorization? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.help.TermsOfService? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.help.TermsOfService - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - if _c1 && _c2 { - return Api.auth.Authorization.authorizationSignUpRequired(flags: _1!, termsOfService: _2) - } - else { - return nil - } - } - - } -} -public extension Api.auth { - enum CodeType: TypeConstructorDescription { - case codeTypeCall - case codeTypeFlashCall - case codeTypeMissedCall - case codeTypeSms - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .codeTypeCall: - if boxed { - buffer.appendInt32(1948046307) - } - - break - case .codeTypeFlashCall: - if boxed { - buffer.appendInt32(577556219) - } - - break - case .codeTypeMissedCall: - if boxed { - buffer.appendInt32(-702884114) - } - - break - case .codeTypeSms: - if boxed { - buffer.appendInt32(1923290508) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .codeTypeCall: - return ("codeTypeCall", []) - case .codeTypeFlashCall: - return ("codeTypeFlashCall", []) - case .codeTypeMissedCall: - return ("codeTypeMissedCall", []) - case .codeTypeSms: - return ("codeTypeSms", []) - } - } - - public static func parse_codeTypeCall(_ reader: BufferReader) -> CodeType? { - return Api.auth.CodeType.codeTypeCall - } - public static func parse_codeTypeFlashCall(_ reader: BufferReader) -> CodeType? { - return Api.auth.CodeType.codeTypeFlashCall - } - public static func parse_codeTypeMissedCall(_ reader: BufferReader) -> CodeType? { - return Api.auth.CodeType.codeTypeMissedCall - } - public static func parse_codeTypeSms(_ reader: BufferReader) -> CodeType? { - return Api.auth.CodeType.codeTypeSms - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api22.swift b/submodules/TelegramApi/Sources/Api22.swift index b9a26d9242..bcde2a9b8b 100644 --- a/submodules/TelegramApi/Sources/Api22.swift +++ b/submodules/TelegramApi/Sources/Api22.swift @@ -1,35 +1,47 @@ -public extension Api.auth { - enum ExportedAuthorization: TypeConstructorDescription { - case exportedAuthorization(id: Int64, bytes: Buffer) +public extension Api { + enum WebPageAttribute: TypeConstructorDescription { + case webPageAttributeTheme(flags: Int32, documents: [Api.Document]?, settings: Api.ThemeSettings?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .exportedAuthorization(let id, let bytes): + case .webPageAttributeTheme(let flags, let documents, let settings): if boxed { - buffer.appendInt32(-1271602504) + buffer.appendInt32(1421174295) } - serializeInt64(id, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents!.count)) + for item in documents! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 1) != 0 {settings!.serialize(buffer, true)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .exportedAuthorization(let id, let bytes): - return ("exportedAuthorization", [("id", String(describing: id)), ("bytes", String(describing: bytes))]) + case .webPageAttributeTheme(let flags, let documents, let settings): + return ("webPageAttributeTheme", [("flags", String(describing: flags)), ("documents", String(describing: documents)), ("settings", String(describing: settings))]) } } - public static func parse_exportedAuthorization(_ reader: BufferReader) -> ExportedAuthorization? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Buffer? - _2 = parseBytes(reader) + public static func parse_webPageAttributeTheme(_ reader: BufferReader) -> WebPageAttribute? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Document]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } } + var _3: Api.ThemeSettings? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.ThemeSettings + } } let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.auth.ExportedAuthorization.exportedAuthorization(id: _1!, bytes: _2!) + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.WebPageAttribute.webPageAttributeTheme(flags: _1!, documents: _2, settings: _3) } else { return nil @@ -38,38 +50,40 @@ public extension Api.auth { } } -public extension Api.auth { - enum LoggedOut: TypeConstructorDescription { - case loggedOut(flags: Int32, futureAuthToken: Buffer?) +public extension Api { + enum WebViewMessageSent: TypeConstructorDescription { + case webViewMessageSent(flags: Int32, msgId: Api.InputBotInlineMessageID?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .loggedOut(let flags, let futureAuthToken): + case .webViewMessageSent(let flags, let msgId): if boxed { - buffer.appendInt32(-1012759713) + buffer.appendInt32(211046684) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {msgId!.serialize(buffer, true)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .loggedOut(let flags, let futureAuthToken): - return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))]) + case .webViewMessageSent(let flags, let msgId): + return ("webViewMessageSent", [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]) } } - public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? { + public static func parse_webViewMessageSent(_ reader: BufferReader) -> WebViewMessageSent? { var _1: Int32? _1 = reader.readInt32() - var _2: Buffer? - if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) } + var _2: Api.InputBotInlineMessageID? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.InputBotInlineMessageID + } } let _c1 = _1 != nil let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil if _c1 && _c2 { - return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2) + return Api.WebViewMessageSent.webViewMessageSent(flags: _1!, msgId: _2) } else { return nil @@ -78,84 +92,38 @@ public extension Api.auth { } } -public extension Api.auth { - enum LoginToken: TypeConstructorDescription { - case loginToken(expires: Int32, token: Buffer) - case loginTokenMigrateTo(dcId: Int32, token: Buffer) - case loginTokenSuccess(authorization: Api.auth.Authorization) +public extension Api { + enum WebViewResult: TypeConstructorDescription { + case webViewResultUrl(queryId: Int64, url: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .loginToken(let expires, let token): + case .webViewResultUrl(let queryId, let url): if boxed { - buffer.appendInt32(1654593920) + buffer.appendInt32(202659196) } - serializeInt32(expires, buffer: buffer, boxed: false) - serializeBytes(token, buffer: buffer, boxed: false) - break - case .loginTokenMigrateTo(let dcId, let token): - if boxed { - buffer.appendInt32(110008598) - } - serializeInt32(dcId, buffer: buffer, boxed: false) - serializeBytes(token, buffer: buffer, boxed: false) - break - case .loginTokenSuccess(let authorization): - if boxed { - buffer.appendInt32(957176926) - } - authorization.serialize(buffer, true) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .loginToken(let expires, let token): - return ("loginToken", [("expires", String(describing: expires)), ("token", String(describing: token))]) - case .loginTokenMigrateTo(let dcId, let token): - return ("loginTokenMigrateTo", [("dcId", String(describing: dcId)), ("token", String(describing: token))]) - case .loginTokenSuccess(let authorization): - return ("loginTokenSuccess", [("authorization", String(describing: authorization))]) + case .webViewResultUrl(let queryId, let url): + return ("webViewResultUrl", [("queryId", String(describing: queryId)), ("url", String(describing: url))]) } } - public static func parse_loginToken(_ reader: BufferReader) -> LoginToken? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) + public static func parse_webViewResultUrl(_ reader: BufferReader) -> WebViewResult? { + var _1: Int64? + _1 = reader.readInt64() + var _2: String? + _2 = parseString(reader) let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.auth.LoginToken.loginToken(expires: _1!, token: _2!) - } - else { - return nil - } - } - public static func parse_loginTokenMigrateTo(_ reader: BufferReader) -> LoginToken? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.auth.LoginToken.loginTokenMigrateTo(dcId: _1!, token: _2!) - } - else { - return nil - } - } - public static func parse_loginTokenSuccess(_ reader: BufferReader) -> LoginToken? { - var _1: Api.auth.Authorization? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - let _c1 = _1 != nil - if _c1 { - return Api.auth.LoginToken.loginTokenSuccess(authorization: _1!) + return Api.WebViewResult.webViewResultUrl(queryId: _1!, url: _2!) } else { return nil @@ -164,1140 +132,394 @@ public extension Api.auth { } } -public extension Api.auth { - enum PasswordRecovery: TypeConstructorDescription { - case passwordRecovery(emailPattern: String) +public extension Api.account { + enum AuthorizationForm: TypeConstructorDescription { + case authorizationForm(flags: Int32, requiredTypes: [Api.SecureRequiredType], values: [Api.SecureValue], errors: [Api.SecureValueError], users: [Api.User], privacyPolicyUrl: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .passwordRecovery(let emailPattern): + case .authorizationForm(let flags, let requiredTypes, let values, let errors, let users, let privacyPolicyUrl): if boxed { - buffer.appendInt32(326715557) - } - serializeString(emailPattern, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .passwordRecovery(let emailPattern): - return ("passwordRecovery", [("emailPattern", String(describing: emailPattern))]) - } - } - - public static func parse_passwordRecovery(_ reader: BufferReader) -> PasswordRecovery? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.auth.PasswordRecovery.passwordRecovery(emailPattern: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.auth { - enum SentCode: TypeConstructorDescription { - case sentCode(flags: Int32, type: Api.auth.SentCodeType, phoneCodeHash: String, nextType: Api.auth.CodeType?, timeout: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sentCode(let flags, let type, let phoneCodeHash, let nextType, let timeout): - if boxed { - buffer.appendInt32(1577067778) + buffer.appendInt32(-1389486888) } serializeInt32(flags, buffer: buffer, boxed: false) - type.serialize(buffer, true) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {nextType!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(requiredTypes.count)) + for item in requiredTypes { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(values.count)) + for item in values { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(errors.count)) + for item in errors { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 0) != 0 {serializeString(privacyPolicyUrl!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .sentCode(let flags, let type, let phoneCodeHash, let nextType, let timeout): - return ("sentCode", [("flags", String(describing: flags)), ("type", String(describing: type)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("nextType", String(describing: nextType)), ("timeout", String(describing: timeout))]) + case .authorizationForm(let flags, let requiredTypes, let values, let errors, let users, let privacyPolicyUrl): + return ("authorizationForm", [("flags", String(describing: flags)), ("requiredTypes", String(describing: requiredTypes)), ("values", String(describing: values)), ("errors", String(describing: errors)), ("users", String(describing: users)), ("privacyPolicyUrl", String(describing: privacyPolicyUrl))]) } } - public static func parse_sentCode(_ reader: BufferReader) -> SentCode? { + public static func parse_authorizationForm(_ reader: BufferReader) -> AuthorizationForm? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.auth.SentCodeType? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.auth.SentCodeType - } - var _3: String? - _3 = parseString(reader) - var _4: Api.auth.CodeType? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.auth.CodeType - } } - var _5: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.auth.SentCode.sentCode(flags: _1!, type: _2!, phoneCodeHash: _3!, nextType: _4, timeout: _5) - } - else { - return nil - } - } - - } -} -public extension Api.auth { - enum SentCodeType: TypeConstructorDescription { - case sentCodeTypeApp(length: Int32) - case sentCodeTypeCall(length: Int32) - case sentCodeTypeFlashCall(pattern: String) - case sentCodeTypeMissedCall(prefix: String, length: Int32) - case sentCodeTypeSms(length: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sentCodeTypeApp(let length): - if boxed { - buffer.appendInt32(1035688326) - } - serializeInt32(length, buffer: buffer, boxed: false) - break - case .sentCodeTypeCall(let length): - if boxed { - buffer.appendInt32(1398007207) - } - serializeInt32(length, buffer: buffer, boxed: false) - break - case .sentCodeTypeFlashCall(let pattern): - if boxed { - buffer.appendInt32(-1425815847) - } - serializeString(pattern, buffer: buffer, boxed: false) - break - case .sentCodeTypeMissedCall(let prefix, let length): - if boxed { - buffer.appendInt32(-2113903484) - } - serializeString(prefix, buffer: buffer, boxed: false) - serializeInt32(length, buffer: buffer, boxed: false) - break - case .sentCodeTypeSms(let length): - if boxed { - buffer.appendInt32(-1073693790) - } - serializeInt32(length, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .sentCodeTypeApp(let length): - return ("sentCodeTypeApp", [("length", String(describing: length))]) - case .sentCodeTypeCall(let length): - return ("sentCodeTypeCall", [("length", String(describing: length))]) - case .sentCodeTypeFlashCall(let pattern): - return ("sentCodeTypeFlashCall", [("pattern", String(describing: pattern))]) - case .sentCodeTypeMissedCall(let prefix, let length): - return ("sentCodeTypeMissedCall", [("prefix", String(describing: prefix)), ("length", String(describing: length))]) - case .sentCodeTypeSms(let length): - return ("sentCodeTypeSms", [("length", String(describing: length))]) - } - } - - public static func parse_sentCodeTypeApp(_ reader: BufferReader) -> SentCodeType? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.auth.SentCodeType.sentCodeTypeApp(length: _1!) - } - else { - return nil - } - } - public static func parse_sentCodeTypeCall(_ reader: BufferReader) -> SentCodeType? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.auth.SentCodeType.sentCodeTypeCall(length: _1!) - } - else { - return nil - } - } - public static func parse_sentCodeTypeFlashCall(_ reader: BufferReader) -> SentCodeType? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.auth.SentCodeType.sentCodeTypeFlashCall(pattern: _1!) - } - else { - return nil - } - } - public static func parse_sentCodeTypeMissedCall(_ reader: BufferReader) -> SentCodeType? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.auth.SentCodeType.sentCodeTypeMissedCall(prefix: _1!, length: _2!) - } - else { - return nil - } - } - public static func parse_sentCodeTypeSms(_ reader: BufferReader) -> SentCodeType? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.auth.SentCodeType.sentCodeTypeSms(length: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.channels { - enum AdminLogResults: TypeConstructorDescription { - case adminLogResults(events: [Api.ChannelAdminLogEvent], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .adminLogResults(let events, let chats, let users): - if boxed { - buffer.appendInt32(-309659827) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(events.count)) - for item in events { - item.serialize(buffer, true) - } - 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 .adminLogResults(let events, let chats, let users): - return ("adminLogResults", [("events", String(describing: events)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_adminLogResults(_ reader: BufferReader) -> AdminLogResults? { - var _1: [Api.ChannelAdminLogEvent]? + var _2: [Api.SecureRequiredType]? if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelAdminLogEvent.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureRequiredType.self) } - var _2: [Api.Chat]? + var _3: [Api.SecureValue]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) } - var _3: [Api.User]? + var _4: [Api.SecureValueError]? if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValueError.self) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.channels.AdminLogResults.adminLogResults(events: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.channels { - enum ChannelParticipant: TypeConstructorDescription { - case channelParticipant(participant: Api.ChannelParticipant, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .channelParticipant(let participant, let chats, let users): - if boxed { - buffer.appendInt32(-541588713) - } - participant.serialize(buffer, true) - 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 .channelParticipant(let participant, let chats, let users): - return ("channelParticipant", [("participant", String(describing: participant)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_channelParticipant(_ reader: BufferReader) -> ChannelParticipant? { - var _1: Api.ChannelParticipant? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant - } - var _2: [Api.Chat]? + var _5: [Api.User]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.channels.ChannelParticipant.channelParticipant(participant: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.channels { - enum ChannelParticipants: TypeConstructorDescription { - case channelParticipants(count: Int32, participants: [Api.ChannelParticipant], chats: [Api.Chat], users: [Api.User]) - case channelParticipantsNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .channelParticipants(let count, let participants, let chats, let users): - if boxed { - buffer.appendInt32(-1699676497) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(participants.count)) - for item in participants { - item.serialize(buffer, true) - } - 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 - case .channelParticipantsNotModified: - if boxed { - buffer.appendInt32(-266911767) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .channelParticipants(let count, let participants, let chats, let users): - return ("channelParticipants", [("count", String(describing: count)), ("participants", String(describing: participants)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .channelParticipantsNotModified: - return ("channelParticipantsNotModified", []) - } - } - - public static func parse_channelParticipants(_ reader: BufferReader) -> ChannelParticipants? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.ChannelParticipant]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelParticipant.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.channels.ChannelParticipants.channelParticipants(count: _1!, participants: _2!, chats: _3!, users: _4!) - } - else { - return nil - } - } - public static func parse_channelParticipantsNotModified(_ reader: BufferReader) -> ChannelParticipants? { - return Api.channels.ChannelParticipants.channelParticipantsNotModified - } - - } -} -public extension Api.channels { - enum SendAsPeers: TypeConstructorDescription { - case sendAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sendAsPeers(let peers, let chats, let users): - if boxed { - buffer.appendInt32(-2091463255) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { - item.serialize(buffer, true) - } - 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 .sendAsPeers(let peers, let chats, let users): - return ("sendAsPeers", [("peers", String(describing: peers)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_sendAsPeers(_ reader: BufferReader) -> SendAsPeers? { - var _1: [Api.Peer]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.channels.SendAsPeers.sendAsPeers(peers: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.contacts { - enum Blocked: TypeConstructorDescription { - case blocked(blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User]) - case blockedSlice(count: Int32, blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .blocked(let blocked, let chats, let users): - if boxed { - buffer.appendInt32(182326673) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocked.count)) - for item in blocked { - item.serialize(buffer, true) - } - 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 - case .blockedSlice(let count, let blocked, let chats, let users): - if boxed { - buffer.appendInt32(-513392236) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(blocked.count)) - for item in blocked { - item.serialize(buffer, true) - } - 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 .blocked(let blocked, let chats, let users): - return ("blocked", [("blocked", String(describing: blocked)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .blockedSlice(let count, let blocked, let chats, let users): - return ("blockedSlice", [("count", String(describing: count)), ("blocked", String(describing: blocked)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_blocked(_ reader: BufferReader) -> Blocked? { - var _1: [Api.PeerBlocked]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerBlocked.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.contacts.Blocked.blocked(blocked: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - public static func parse_blockedSlice(_ reader: BufferReader) -> Blocked? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.PeerBlocked]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerBlocked.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.contacts.Blocked.blockedSlice(count: _1!, blocked: _2!, chats: _3!, users: _4!) - } - else { - return nil - } - } - - } -} -public extension Api.contacts { - enum Contacts: TypeConstructorDescription { - case contacts(contacts: [Api.Contact], savedCount: Int32, users: [Api.User]) - case contactsNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .contacts(let contacts, let savedCount, let users): - if boxed { - buffer.appendInt32(-353862078) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(contacts.count)) - for item in contacts { - item.serialize(buffer, true) - } - serializeInt32(savedCount, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - case .contactsNotModified: - if boxed { - buffer.appendInt32(-1219778094) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .contacts(let contacts, let savedCount, let users): - return ("contacts", [("contacts", String(describing: contacts)), ("savedCount", String(describing: savedCount)), ("users", String(describing: users))]) - case .contactsNotModified: - return ("contactsNotModified", []) - } - } - - public static func parse_contacts(_ reader: BufferReader) -> Contacts? { - var _1: [Api.Contact]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Contact.self) - } - var _2: Int32? - _2 = reader.readInt32() - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.contacts.Contacts.contacts(contacts: _1!, savedCount: _2!, users: _3!) - } - else { - return nil - } - } - public static func parse_contactsNotModified(_ reader: BufferReader) -> Contacts? { - return Api.contacts.Contacts.contactsNotModified - } - - } -} -public extension Api.contacts { - enum Found: TypeConstructorDescription { - case found(myResults: [Api.Peer], results: [Api.Peer], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .found(let myResults, let results, let chats, let users): - if boxed { - buffer.appendInt32(-1290580579) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(myResults.count)) - for item in myResults { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(results.count)) - for item in results { - item.serialize(buffer, true) - } - 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 .found(let myResults, let results, let chats, let users): - return ("found", [("myResults", String(describing: myResults)), ("results", String(describing: results)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_found(_ reader: BufferReader) -> Found? { - var _1: [Api.Peer]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) - } - var _2: [Api.Peer]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.contacts.Found.found(myResults: _1!, results: _2!, chats: _3!, users: _4!) - } - else { - return nil - } - } - - } -} -public extension Api.contacts { - enum ImportedContacts: TypeConstructorDescription { - case importedContacts(imported: [Api.ImportedContact], popularInvites: [Api.PopularContact], retryContacts: [Int64], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .importedContacts(let imported, let popularInvites, let retryContacts, let users): - if boxed { - buffer.appendInt32(2010127419) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(imported.count)) - for item in imported { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(popularInvites.count)) - for item in popularInvites { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(retryContacts.count)) - for item in retryContacts { - serializeInt64(item, 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 .importedContacts(let imported, let popularInvites, let retryContacts, let users): - return ("importedContacts", [("imported", String(describing: imported)), ("popularInvites", String(describing: popularInvites)), ("retryContacts", String(describing: retryContacts)), ("users", String(describing: users))]) - } - } - - public static func parse_importedContacts(_ reader: BufferReader) -> ImportedContacts? { - var _1: [Api.ImportedContact]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ImportedContact.self) - } - var _2: [Api.PopularContact]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PopularContact.self) - } - var _3: [Int64]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.contacts.ImportedContacts.importedContacts(imported: _1!, popularInvites: _2!, retryContacts: _3!, users: _4!) - } - else { - return nil - } - } - - } -} -public extension Api.contacts { - enum ResolvedPeer: TypeConstructorDescription { - case resolvedPeer(peer: Api.Peer, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .resolvedPeer(let peer, let chats, let users): - if boxed { - buffer.appendInt32(2131196633) - } - peer.serialize(buffer, true) - 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 .resolvedPeer(let peer, let chats, let users): - return ("resolvedPeer", [("peer", String(describing: peer)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_resolvedPeer(_ reader: BufferReader) -> ResolvedPeer? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.contacts.ResolvedPeer.resolvedPeer(peer: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.contacts { - enum TopPeers: TypeConstructorDescription { - case topPeers(categories: [Api.TopPeerCategoryPeers], chats: [Api.Chat], users: [Api.User]) - case topPeersDisabled - case topPeersNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .topPeers(let categories, let chats, let users): - if boxed { - buffer.appendInt32(1891070632) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(categories.count)) - for item in categories { - item.serialize(buffer, true) - } - 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 - case .topPeersDisabled: - if boxed { - buffer.appendInt32(-1255369827) - } - - break - case .topPeersNotModified: - if boxed { - buffer.appendInt32(-567906571) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .topPeers(let categories, let chats, let users): - return ("topPeers", [("categories", String(describing: categories)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .topPeersDisabled: - return ("topPeersDisabled", []) - case .topPeersNotModified: - return ("topPeersNotModified", []) - } - } - - public static func parse_topPeers(_ reader: BufferReader) -> TopPeers? { - var _1: [Api.TopPeerCategoryPeers]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.TopPeerCategoryPeers.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.contacts.TopPeers.topPeers(categories: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - public static func parse_topPeersDisabled(_ reader: BufferReader) -> TopPeers? { - return Api.contacts.TopPeers.topPeersDisabled - } - public static func parse_topPeersNotModified(_ reader: BufferReader) -> TopPeers? { - return Api.contacts.TopPeers.topPeersNotModified - } - - } -} -public extension Api.help { - enum AppUpdate: TypeConstructorDescription { - case appUpdate(flags: Int32, id: Int32, version: String, text: String, entities: [Api.MessageEntity], document: Api.Document?, url: String?, sticker: Api.Document?) - case noAppUpdate - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .appUpdate(let flags, let id, let version, let text, let entities, let document, let url, let sticker): - if boxed { - buffer.appendInt32(-860107216) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeString(version, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities.count)) - for item in entities { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 1) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {sticker!.serialize(buffer, true)} - break - case .noAppUpdate: - if boxed { - buffer.appendInt32(-1000708810) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .appUpdate(let flags, let id, let version, let text, let entities, let document, let url, let sticker): - return ("appUpdate", [("flags", String(describing: flags)), ("id", String(describing: id)), ("version", String(describing: version)), ("text", String(describing: text)), ("entities", String(describing: entities)), ("document", String(describing: document)), ("url", String(describing: url)), ("sticker", String(describing: sticker))]) - case .noAppUpdate: - return ("noAppUpdate", []) - } - } - - public static func parse_appUpdate(_ reader: BufferReader) -> AppUpdate? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: [Api.MessageEntity]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } - var _6: Api.Document? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.Document - } } - var _7: String? - if Int(_1!) & Int(1 << 2) != 0 {_7 = parseString(reader) } - var _8: Api.Document? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.Document - } } + var _6: String? + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.help.AppUpdate.appUpdate(flags: _1!, id: _2!, version: _3!, text: _4!, entities: _5!, document: _6, url: _7, sticker: _8) + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.account.AuthorizationForm.authorizationForm(flags: _1!, requiredTypes: _2!, values: _3!, errors: _4!, users: _5!, privacyPolicyUrl: _6) } else { return nil } } - public static func parse_noAppUpdate(_ reader: BufferReader) -> AppUpdate? { - return Api.help.AppUpdate.noAppUpdate - } } } -public extension Api.help { - enum CountriesList: TypeConstructorDescription { - case countriesList(countries: [Api.help.Country], hash: Int32) - case countriesListNotModified +public extension Api.account { + enum Authorizations: TypeConstructorDescription { + case authorizations(authorizationTtlDays: Int32, authorizations: [Api.Authorization]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .countriesList(let countries, let hash): + case .authorizations(let authorizationTtlDays, let authorizations): if boxed { - buffer.appendInt32(-2016381538) + buffer.appendInt32(1275039392) } + serializeInt32(authorizationTtlDays, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(countries.count)) - for item in countries { + buffer.appendInt32(Int32(authorizations.count)) + for item in authorizations { item.serialize(buffer, true) } - serializeInt32(hash, buffer: buffer, boxed: false) - break - case .countriesListNotModified: - if boxed { - buffer.appendInt32(-1815339214) - } - break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .countriesList(let countries, let hash): - return ("countriesList", [("countries", String(describing: countries)), ("hash", String(describing: hash))]) - case .countriesListNotModified: - return ("countriesListNotModified", []) + case .authorizations(let authorizationTtlDays, let authorizations): + return ("authorizations", [("authorizationTtlDays", String(describing: authorizationTtlDays)), ("authorizations", String(describing: authorizations))]) } } - public static func parse_countriesList(_ reader: BufferReader) -> CountriesList? { - var _1: [Api.help.Country]? + public static func parse_authorizations(_ reader: BufferReader) -> Authorizations? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Authorization]? if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.Country.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Authorization.self) } - var _2: Int32? - _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.help.CountriesList.countriesList(countries: _1!, hash: _2!) + return Api.account.Authorizations.authorizations(authorizationTtlDays: _1!, authorizations: _2!) } else { return nil } } - public static func parse_countriesListNotModified(_ reader: BufferReader) -> CountriesList? { - return Api.help.CountriesList.countriesListNotModified - } } } -public extension Api.help { - enum Country: TypeConstructorDescription { - case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode]) +public extension Api.account { + enum AutoDownloadSettings: TypeConstructorDescription { + case autoDownloadSettings(low: Api.AutoDownloadSettings, medium: Api.AutoDownloadSettings, high: Api.AutoDownloadSettings) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .country(let flags, let iso2, let defaultName, let name, let countryCodes): + case .autoDownloadSettings(let low, let medium, let high): if boxed { - buffer.appendInt32(-1014526429) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(iso2, buffer: buffer, boxed: false) - serializeString(defaultName, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(countryCodes.count)) - for item in countryCodes { - item.serialize(buffer, true) + buffer.appendInt32(1674235686) } + low.serialize(buffer, true) + medium.serialize(buffer, true) + high.serialize(buffer, true) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .country(let flags, let iso2, let defaultName, let name, let countryCodes): - return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))]) + case .autoDownloadSettings(let low, let medium, let high): + return ("autoDownloadSettings", [("low", String(describing: low)), ("medium", String(describing: medium)), ("high", String(describing: high))]) } } - public static func parse_country(_ reader: BufferReader) -> Country? { + public static func parse_autoDownloadSettings(_ reader: BufferReader) -> AutoDownloadSettings? { + var _1: Api.AutoDownloadSettings? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings + } + var _2: Api.AutoDownloadSettings? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings + } + var _3: Api.AutoDownloadSettings? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.AutoDownloadSettings + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.account.AutoDownloadSettings.autoDownloadSettings(low: _1!, medium: _2!, high: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum ContentSettings: TypeConstructorDescription { + case contentSettings(flags: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .contentSettings(let flags): + if boxed { + buffer.appendInt32(1474462241) + } + serializeInt32(flags, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .contentSettings(let flags): + return ("contentSettings", [("flags", String(describing: flags))]) + } + } + + public static func parse_contentSettings(_ reader: BufferReader) -> ContentSettings? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.account.ContentSettings.contentSettings(flags: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum Password: TypeConstructorDescription { + case password(flags: Int32, currentAlgo: Api.PasswordKdfAlgo?, srpB: Buffer?, srpId: Int64?, hint: String?, emailUnconfirmedPattern: String?, newAlgo: Api.PasswordKdfAlgo, newSecureAlgo: Api.SecurePasswordKdfAlgo, secureRandom: Buffer, pendingResetDate: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .password(let flags, let currentAlgo, let srpB, let srpId, let hint, let emailUnconfirmedPattern, let newAlgo, let newSecureAlgo, let secureRandom, let pendingResetDate): + if boxed { + buffer.appendInt32(408623183) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {currentAlgo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeBytes(srpB!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt64(srpId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(hint!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeString(emailUnconfirmedPattern!, buffer: buffer, boxed: false)} + newAlgo.serialize(buffer, true) + newSecureAlgo.serialize(buffer, true) + serializeBytes(secureRandom, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 5) != 0 {serializeInt32(pendingResetDate!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .password(let flags, let currentAlgo, let srpB, let srpId, let hint, let emailUnconfirmedPattern, let newAlgo, let newSecureAlgo, let secureRandom, let pendingResetDate): + return ("password", [("flags", String(describing: flags)), ("currentAlgo", String(describing: currentAlgo)), ("srpB", String(describing: srpB)), ("srpId", String(describing: srpId)), ("hint", String(describing: hint)), ("emailUnconfirmedPattern", String(describing: emailUnconfirmedPattern)), ("newAlgo", String(describing: newAlgo)), ("newSecureAlgo", String(describing: newSecureAlgo)), ("secureRandom", String(describing: secureRandom)), ("pendingResetDate", String(describing: pendingResetDate))]) + } + } + + public static func parse_password(_ reader: BufferReader) -> Password? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.PasswordKdfAlgo? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo + } } + var _3: Buffer? + if Int(_1!) & Int(1 << 2) != 0 {_3 = parseBytes(reader) } + var _4: Int64? + if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt64() } + var _5: String? + if Int(_1!) & Int(1 << 3) != 0 {_5 = parseString(reader) } + var _6: String? + if Int(_1!) & Int(1 << 4) != 0 {_6 = parseString(reader) } + var _7: Api.PasswordKdfAlgo? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo + } + var _8: Api.SecurePasswordKdfAlgo? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.SecurePasswordKdfAlgo + } + var _9: Buffer? + _9 = parseBytes(reader) + var _10: Int32? + if Int(_1!) & Int(1 << 5) != 0 {_10 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = (Int(_1!) & Int(1 << 5) == 0) || _10 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { + return Api.account.Password.password(flags: _1!, currentAlgo: _2, srpB: _3, srpId: _4, hint: _5, emailUnconfirmedPattern: _6, newAlgo: _7!, newSecureAlgo: _8!, secureRandom: _9!, pendingResetDate: _10) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum PasswordInputSettings: TypeConstructorDescription { + case passwordInputSettings(flags: Int32, newAlgo: Api.PasswordKdfAlgo?, newPasswordHash: Buffer?, hint: String?, email: String?, newSecureSettings: Api.SecureSecretSettings?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .passwordInputSettings(let flags, let newAlgo, let newPasswordHash, let hint, let email, let newSecureSettings): + if boxed { + buffer.appendInt32(-1036572727) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {newAlgo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(newPasswordHash!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeString(hint!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(email!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {newSecureSettings!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .passwordInputSettings(let flags, let newAlgo, let newPasswordHash, let hint, let email, let newSecureSettings): + return ("passwordInputSettings", [("flags", String(describing: flags)), ("newAlgo", String(describing: newAlgo)), ("newPasswordHash", String(describing: newPasswordHash)), ("hint", String(describing: hint)), ("email", String(describing: email)), ("newSecureSettings", String(describing: newSecureSettings))]) + } + } + + public static func parse_passwordInputSettings(_ reader: BufferReader) -> PasswordInputSettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.PasswordKdfAlgo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PasswordKdfAlgo + } } + var _3: Buffer? + if Int(_1!) & Int(1 << 0) != 0 {_3 = parseBytes(reader) } + var _4: String? + if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) } + var _5: String? + if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) } + var _6: Api.SecureSecretSettings? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.SecureSecretSettings + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.account.PasswordInputSettings.passwordInputSettings(flags: _1!, newAlgo: _2, newPasswordHash: _3, hint: _4, email: _5, newSecureSettings: _6) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum PasswordSettings: TypeConstructorDescription { + case passwordSettings(flags: Int32, email: String?, secureSettings: Api.SecureSecretSettings?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .passwordSettings(let flags, let email, let secureSettings): + if boxed { + buffer.appendInt32(-1705233435) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(email!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {secureSettings!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .passwordSettings(let flags, let email, let secureSettings): + return ("passwordSettings", [("flags", String(describing: flags)), ("email", String(describing: email)), ("secureSettings", String(describing: secureSettings))]) + } + } + + public static func parse_passwordSettings(_ reader: BufferReader) -> PasswordSettings? { var _1: Int32? _1 = reader.readInt32() var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } - var _5: [Api.help.CountryCode]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self) - } + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: Api.SecureSecretSettings? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.SecureSecretSettings + } } let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!) + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.account.PasswordSettings.passwordSettings(flags: _1!, email: _2, secureSettings: _3) } else { return nil @@ -1306,3 +528,665 @@ public extension Api.help { } } +public extension Api.account { + enum PrivacyRules: TypeConstructorDescription { + case privacyRules(rules: [Api.PrivacyRule], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .privacyRules(let rules, let chats, let users): + if boxed { + buffer.appendInt32(1352683077) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rules.count)) + for item in rules { + item.serialize(buffer, true) + } + 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 .privacyRules(let rules, let chats, let users): + return ("privacyRules", [("rules", String(describing: rules)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_privacyRules(_ reader: BufferReader) -> PrivacyRules? { + var _1: [Api.PrivacyRule]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.account.PrivacyRules.privacyRules(rules: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum ResetPasswordResult: TypeConstructorDescription { + case resetPasswordFailedWait(retryDate: Int32) + case resetPasswordOk + case resetPasswordRequestedWait(untilDate: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .resetPasswordFailedWait(let retryDate): + if boxed { + buffer.appendInt32(-478701471) + } + serializeInt32(retryDate, buffer: buffer, boxed: false) + break + case .resetPasswordOk: + if boxed { + buffer.appendInt32(-383330754) + } + + break + case .resetPasswordRequestedWait(let untilDate): + if boxed { + buffer.appendInt32(-370148227) + } + serializeInt32(untilDate, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .resetPasswordFailedWait(let retryDate): + return ("resetPasswordFailedWait", [("retryDate", String(describing: retryDate))]) + case .resetPasswordOk: + return ("resetPasswordOk", []) + case .resetPasswordRequestedWait(let untilDate): + return ("resetPasswordRequestedWait", [("untilDate", String(describing: untilDate))]) + } + } + + public static func parse_resetPasswordFailedWait(_ reader: BufferReader) -> ResetPasswordResult? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.account.ResetPasswordResult.resetPasswordFailedWait(retryDate: _1!) + } + else { + return nil + } + } + public static func parse_resetPasswordOk(_ reader: BufferReader) -> ResetPasswordResult? { + return Api.account.ResetPasswordResult.resetPasswordOk + } + public static func parse_resetPasswordRequestedWait(_ reader: BufferReader) -> ResetPasswordResult? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.account.ResetPasswordResult.resetPasswordRequestedWait(untilDate: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum SavedRingtone: TypeConstructorDescription { + case savedRingtone + case savedRingtoneConverted(document: Api.Document) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .savedRingtone: + if boxed { + buffer.appendInt32(-1222230163) + } + + break + case .savedRingtoneConverted(let document): + if boxed { + buffer.appendInt32(523271863) + } + document.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .savedRingtone: + return ("savedRingtone", []) + case .savedRingtoneConverted(let document): + return ("savedRingtoneConverted", [("document", String(describing: document))]) + } + } + + public static func parse_savedRingtone(_ reader: BufferReader) -> SavedRingtone? { + return Api.account.SavedRingtone.savedRingtone + } + public static func parse_savedRingtoneConverted(_ reader: BufferReader) -> SavedRingtone? { + var _1: Api.Document? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Document + } + let _c1 = _1 != nil + if _c1 { + return Api.account.SavedRingtone.savedRingtoneConverted(document: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum SavedRingtones: TypeConstructorDescription { + case savedRingtones(hash: Int64, ringtones: [Api.Document]) + case savedRingtonesNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .savedRingtones(let hash, let ringtones): + if boxed { + buffer.appendInt32(-1041683259) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(ringtones.count)) + for item in ringtones { + item.serialize(buffer, true) + } + break + case .savedRingtonesNotModified: + if boxed { + buffer.appendInt32(-67704655) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .savedRingtones(let hash, let ringtones): + return ("savedRingtones", [("hash", String(describing: hash)), ("ringtones", String(describing: ringtones))]) + case .savedRingtonesNotModified: + return ("savedRingtonesNotModified", []) + } + } + + public static func parse_savedRingtones(_ reader: BufferReader) -> SavedRingtones? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.Document]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.SavedRingtones.savedRingtones(hash: _1!, ringtones: _2!) + } + else { + return nil + } + } + public static func parse_savedRingtonesNotModified(_ reader: BufferReader) -> SavedRingtones? { + return Api.account.SavedRingtones.savedRingtonesNotModified + } + + } +} +public extension Api.account { + enum SentEmailCode: TypeConstructorDescription { + case sentEmailCode(emailPattern: String, length: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .sentEmailCode(let emailPattern, let length): + if boxed { + buffer.appendInt32(-2128640689) + } + serializeString(emailPattern, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .sentEmailCode(let emailPattern, let length): + return ("sentEmailCode", [("emailPattern", String(describing: emailPattern)), ("length", String(describing: length))]) + } + } + + public static func parse_sentEmailCode(_ reader: BufferReader) -> SentEmailCode? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.SentEmailCode.sentEmailCode(emailPattern: _1!, length: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum Takeout: TypeConstructorDescription { + case takeout(id: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .takeout(let id): + if boxed { + buffer.appendInt32(1304052993) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .takeout(let id): + return ("takeout", [("id", String(describing: id))]) + } + } + + public static func parse_takeout(_ reader: BufferReader) -> Takeout? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.account.Takeout.takeout(id: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum Themes: TypeConstructorDescription { + case themes(hash: Int64, themes: [Api.Theme]) + case themesNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .themes(let hash, let themes): + if boxed { + buffer.appendInt32(-1707242387) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(themes.count)) + for item in themes { + item.serialize(buffer, true) + } + break + case .themesNotModified: + if boxed { + buffer.appendInt32(-199313886) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .themes(let hash, let themes): + return ("themes", [("hash", String(describing: hash)), ("themes", String(describing: themes))]) + case .themesNotModified: + return ("themesNotModified", []) + } + } + + public static func parse_themes(_ reader: BufferReader) -> Themes? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.Theme]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Theme.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.Themes.themes(hash: _1!, themes: _2!) + } + else { + return nil + } + } + public static func parse_themesNotModified(_ reader: BufferReader) -> Themes? { + return Api.account.Themes.themesNotModified + } + + } +} +public extension Api.account { + enum TmpPassword: TypeConstructorDescription { + case tmpPassword(tmpPassword: Buffer, validUntil: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .tmpPassword(let tmpPassword, let validUntil): + if boxed { + buffer.appendInt32(-614138572) + } + serializeBytes(tmpPassword, buffer: buffer, boxed: false) + serializeInt32(validUntil, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .tmpPassword(let tmpPassword, let validUntil): + return ("tmpPassword", [("tmpPassword", String(describing: tmpPassword)), ("validUntil", String(describing: validUntil))]) + } + } + + public static func parse_tmpPassword(_ reader: BufferReader) -> TmpPassword? { + var _1: Buffer? + _1 = parseBytes(reader) + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.TmpPassword.tmpPassword(tmpPassword: _1!, validUntil: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.account { + enum WallPapers: TypeConstructorDescription { + case wallPapers(hash: Int64, wallpapers: [Api.WallPaper]) + case wallPapersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .wallPapers(let hash, let wallpapers): + if boxed { + buffer.appendInt32(-842824308) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(wallpapers.count)) + for item in wallpapers { + item.serialize(buffer, true) + } + break + case .wallPapersNotModified: + if boxed { + buffer.appendInt32(471437699) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .wallPapers(let hash, let wallpapers): + return ("wallPapers", [("hash", String(describing: hash)), ("wallpapers", String(describing: wallpapers))]) + case .wallPapersNotModified: + return ("wallPapersNotModified", []) + } + } + + public static func parse_wallPapers(_ reader: BufferReader) -> WallPapers? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.WallPaper]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WallPaper.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.WallPapers.wallPapers(hash: _1!, wallpapers: _2!) + } + else { + return nil + } + } + public static func parse_wallPapersNotModified(_ reader: BufferReader) -> WallPapers? { + return Api.account.WallPapers.wallPapersNotModified + } + + } +} +public extension Api.account { + enum WebAuthorizations: TypeConstructorDescription { + case webAuthorizations(authorizations: [Api.WebAuthorization], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .webAuthorizations(let authorizations, let users): + if boxed { + buffer.appendInt32(-313079300) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(authorizations.count)) + for item in authorizations { + 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 .webAuthorizations(let authorizations, let users): + return ("webAuthorizations", [("authorizations", String(describing: authorizations)), ("users", String(describing: users))]) + } + } + + public static func parse_webAuthorizations(_ reader: BufferReader) -> WebAuthorizations? { + var _1: [Api.WebAuthorization]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.WebAuthorization.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.account.WebAuthorizations.webAuthorizations(authorizations: _1!, users: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.auth { + enum Authorization: TypeConstructorDescription { + case authorization(flags: Int32, otherwiseReloginDays: Int32?, tmpSessions: Int32?, user: Api.User) + case authorizationSignUpRequired(flags: Int32, termsOfService: Api.help.TermsOfService?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user): + if boxed { + buffer.appendInt32(872119224) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(otherwiseReloginDays!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)} + user.serialize(buffer, true) + break + case .authorizationSignUpRequired(let flags, let termsOfService): + if boxed { + buffer.appendInt32(1148485274) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {termsOfService!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .authorization(let flags, let otherwiseReloginDays, let tmpSessions, let user): + return ("authorization", [("flags", String(describing: flags)), ("otherwiseReloginDays", String(describing: otherwiseReloginDays)), ("tmpSessions", String(describing: tmpSessions)), ("user", String(describing: user))]) + case .authorizationSignUpRequired(let flags, let termsOfService): + return ("authorizationSignUpRequired", [("flags", String(describing: flags)), ("termsOfService", String(describing: termsOfService))]) + } + } + + public static func parse_authorization(_ reader: BufferReader) -> Authorization? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Api.User? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.User + } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.auth.Authorization.authorization(flags: _1!, otherwiseReloginDays: _2, tmpSessions: _3, user: _4!) + } + else { + return nil + } + } + public static func parse_authorizationSignUpRequired(_ reader: BufferReader) -> Authorization? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.help.TermsOfService? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.help.TermsOfService + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + if _c1 && _c2 { + return Api.auth.Authorization.authorizationSignUpRequired(flags: _1!, termsOfService: _2) + } + else { + return nil + } + } + + } +} +public extension Api.auth { + enum CodeType: TypeConstructorDescription { + case codeTypeCall + case codeTypeFlashCall + case codeTypeMissedCall + case codeTypeSms + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .codeTypeCall: + if boxed { + buffer.appendInt32(1948046307) + } + + break + case .codeTypeFlashCall: + if boxed { + buffer.appendInt32(577556219) + } + + break + case .codeTypeMissedCall: + if boxed { + buffer.appendInt32(-702884114) + } + + break + case .codeTypeSms: + if boxed { + buffer.appendInt32(1923290508) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .codeTypeCall: + return ("codeTypeCall", []) + case .codeTypeFlashCall: + return ("codeTypeFlashCall", []) + case .codeTypeMissedCall: + return ("codeTypeMissedCall", []) + case .codeTypeSms: + return ("codeTypeSms", []) + } + } + + public static func parse_codeTypeCall(_ reader: BufferReader) -> CodeType? { + return Api.auth.CodeType.codeTypeCall + } + public static func parse_codeTypeFlashCall(_ reader: BufferReader) -> CodeType? { + return Api.auth.CodeType.codeTypeFlashCall + } + public static func parse_codeTypeMissedCall(_ reader: BufferReader) -> CodeType? { + return Api.auth.CodeType.codeTypeMissedCall + } + public static func parse_codeTypeSms(_ reader: BufferReader) -> CodeType? { + return Api.auth.CodeType.codeTypeSms + } + + } +} diff --git a/submodules/TelegramApi/Sources/Api23.swift b/submodules/TelegramApi/Sources/Api23.swift index 706f76027d..b9a26d9242 100644 --- a/submodules/TelegramApi/Sources/Api23.swift +++ b/submodules/TelegramApi/Sources/Api23.swift @@ -1,55 +1,35 @@ -public extension Api.help { - enum CountryCode: TypeConstructorDescription { - case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?) +public extension Api.auth { + enum ExportedAuthorization: TypeConstructorDescription { + case exportedAuthorization(id: Int64, bytes: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .countryCode(let flags, let countryCode, let prefixes, let patterns): + case .exportedAuthorization(let id, let bytes): if boxed { - buffer.appendInt32(1107543535) + buffer.appendInt32(-1271602504) } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(countryCode, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(prefixes!.count)) - for item in prefixes! { - serializeString(item, buffer: buffer, boxed: false) - }} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(patterns!.count)) - for item in patterns! { - serializeString(item, buffer: buffer, boxed: false) - }} + serializeInt64(id, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .countryCode(let flags, let countryCode, let prefixes, let patterns): - return ("countryCode", [("flags", String(describing: flags)), ("countryCode", String(describing: countryCode)), ("prefixes", String(describing: prefixes)), ("patterns", String(describing: patterns))]) + case .exportedAuthorization(let id, let bytes): + return ("exportedAuthorization", [("id", String(describing: id)), ("bytes", String(describing: bytes))]) } } - public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: [String]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) - } } - var _4: [String]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) - } } + public static func parse_exportedAuthorization(_ reader: BufferReader) -> ExportedAuthorization? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Buffer? + _2 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4) + if _c1 && _c2 { + return Api.auth.ExportedAuthorization.exportedAuthorization(id: _1!, bytes: _2!) } else { return nil @@ -58,96 +38,160 @@ public extension Api.help { } } -public extension Api.help { - enum DeepLinkInfo: TypeConstructorDescription { - case deepLinkInfo(flags: Int32, message: String, entities: [Api.MessageEntity]?) - case deepLinkInfoEmpty +public extension Api.auth { + enum LoggedOut: TypeConstructorDescription { + case loggedOut(flags: Int32, futureAuthToken: Buffer?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .deepLinkInfo(let flags, let message, let entities): + case .loggedOut(let flags, let futureAuthToken): if boxed { - buffer.appendInt32(1783556146) + buffer.appendInt32(-1012759713) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - break - case .deepLinkInfoEmpty: - if boxed { - buffer.appendInt32(1722786150) - } - + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(futureAuthToken!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .deepLinkInfo(let flags, let message, let entities): - return ("deepLinkInfo", [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))]) - case .deepLinkInfoEmpty: - return ("deepLinkInfoEmpty", []) + case .loggedOut(let flags, let futureAuthToken): + return ("loggedOut", [("flags", String(describing: flags)), ("futureAuthToken", String(describing: futureAuthToken))]) } } - public static func parse_deepLinkInfo(_ reader: BufferReader) -> DeepLinkInfo? { + public static func parse_loggedOut(_ reader: BufferReader) -> LoggedOut? { var _1: Int32? _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } + var _2: Buffer? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseBytes(reader) } let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.help.DeepLinkInfo.deepLinkInfo(flags: _1!, message: _2!, entities: _3) + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + if _c1 && _c2 { + return Api.auth.LoggedOut.loggedOut(flags: _1!, futureAuthToken: _2) } else { return nil } } - public static func parse_deepLinkInfoEmpty(_ reader: BufferReader) -> DeepLinkInfo? { - return Api.help.DeepLinkInfo.deepLinkInfoEmpty - } } } -public extension Api.help { - enum InviteText: TypeConstructorDescription { - case inviteText(message: String) +public extension Api.auth { + enum LoginToken: TypeConstructorDescription { + case loginToken(expires: Int32, token: Buffer) + case loginTokenMigrateTo(dcId: Int32, token: Buffer) + case loginTokenSuccess(authorization: Api.auth.Authorization) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .inviteText(let message): + case .loginToken(let expires, let token): if boxed { - buffer.appendInt32(415997816) + buffer.appendInt32(1654593920) } - serializeString(message, buffer: buffer, boxed: false) + serializeInt32(expires, buffer: buffer, boxed: false) + serializeBytes(token, buffer: buffer, boxed: false) + break + case .loginTokenMigrateTo(let dcId, let token): + if boxed { + buffer.appendInt32(110008598) + } + serializeInt32(dcId, buffer: buffer, boxed: false) + serializeBytes(token, buffer: buffer, boxed: false) + break + case .loginTokenSuccess(let authorization): + if boxed { + buffer.appendInt32(957176926) + } + authorization.serialize(buffer, true) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .inviteText(let message): - return ("inviteText", [("message", String(describing: message))]) + case .loginToken(let expires, let token): + return ("loginToken", [("expires", String(describing: expires)), ("token", String(describing: token))]) + case .loginTokenMigrateTo(let dcId, let token): + return ("loginTokenMigrateTo", [("dcId", String(describing: dcId)), ("token", String(describing: token))]) + case .loginTokenSuccess(let authorization): + return ("loginTokenSuccess", [("authorization", String(describing: authorization))]) } } - public static func parse_inviteText(_ reader: BufferReader) -> InviteText? { + public static func parse_loginToken(_ reader: BufferReader) -> LoginToken? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.auth.LoginToken.loginToken(expires: _1!, token: _2!) + } + else { + return nil + } + } + public static func parse_loginTokenMigrateTo(_ reader: BufferReader) -> LoginToken? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Buffer? + _2 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.auth.LoginToken.loginTokenMigrateTo(dcId: _1!, token: _2!) + } + else { + return nil + } + } + public static func parse_loginTokenSuccess(_ reader: BufferReader) -> LoginToken? { + var _1: Api.auth.Authorization? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + let _c1 = _1 != nil + if _c1 { + return Api.auth.LoginToken.loginTokenSuccess(authorization: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.auth { + enum PasswordRecovery: TypeConstructorDescription { + case passwordRecovery(emailPattern: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .passwordRecovery(let emailPattern): + if boxed { + buffer.appendInt32(326715557) + } + serializeString(emailPattern, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .passwordRecovery(let emailPattern): + return ("passwordRecovery", [("emailPattern", String(describing: emailPattern))]) + } + } + + public static func parse_passwordRecovery(_ reader: BufferReader) -> PasswordRecovery? { var _1: String? _1 = parseString(reader) let _c1 = _1 != nil if _c1 { - return Api.help.InviteText.inviteText(message: _1!) + return Api.auth.PasswordRecovery.passwordRecovery(emailPattern: _1!) } else { return nil @@ -156,88 +200,202 @@ public extension Api.help { } } -public extension Api.help { - enum PassportConfig: TypeConstructorDescription { - case passportConfig(hash: Int32, countriesLangs: Api.DataJSON) - case passportConfigNotModified +public extension Api.auth { + enum SentCode: TypeConstructorDescription { + case sentCode(flags: Int32, type: Api.auth.SentCodeType, phoneCodeHash: String, nextType: Api.auth.CodeType?, timeout: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .passportConfig(let hash, let countriesLangs): + case .sentCode(let flags, let type, let phoneCodeHash, let nextType, let timeout): if boxed { - buffer.appendInt32(-1600596305) + buffer.appendInt32(1577067778) } - serializeInt32(hash, buffer: buffer, boxed: false) - countriesLangs.serialize(buffer, true) - break - case .passportConfigNotModified: - if boxed { - buffer.appendInt32(-1078332329) - } - + serializeInt32(flags, buffer: buffer, boxed: false) + type.serialize(buffer, true) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {nextType!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .passportConfig(let hash, let countriesLangs): - return ("passportConfig", [("hash", String(describing: hash)), ("countriesLangs", String(describing: countriesLangs))]) - case .passportConfigNotModified: - return ("passportConfigNotModified", []) + case .sentCode(let flags, let type, let phoneCodeHash, let nextType, let timeout): + return ("sentCode", [("flags", String(describing: flags)), ("type", String(describing: type)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("nextType", String(describing: nextType)), ("timeout", String(describing: timeout))]) } } - public static func parse_passportConfig(_ reader: BufferReader) -> PassportConfig? { + public static func parse_sentCode(_ reader: BufferReader) -> SentCode? { var _1: Int32? _1 = reader.readInt32() - var _2: Api.DataJSON? + var _2: Api.auth.SentCodeType? if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DataJSON + _2 = Api.parse(reader, signature: signature) as? Api.auth.SentCodeType } + var _3: String? + _3 = parseString(reader) + var _4: Api.auth.CodeType? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.auth.CodeType + } } + var _5: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.help.PassportConfig.passportConfig(hash: _1!, countriesLangs: _2!) + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.auth.SentCode.sentCode(flags: _1!, type: _2!, phoneCodeHash: _3!, nextType: _4, timeout: _5) } else { return nil } } - public static func parse_passportConfigNotModified(_ reader: BufferReader) -> PassportConfig? { - return Api.help.PassportConfig.passportConfigNotModified + + } +} +public extension Api.auth { + enum SentCodeType: TypeConstructorDescription { + case sentCodeTypeApp(length: Int32) + case sentCodeTypeCall(length: Int32) + case sentCodeTypeFlashCall(pattern: String) + case sentCodeTypeMissedCall(prefix: String, length: Int32) + case sentCodeTypeSms(length: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .sentCodeTypeApp(let length): + if boxed { + buffer.appendInt32(1035688326) + } + serializeInt32(length, buffer: buffer, boxed: false) + break + case .sentCodeTypeCall(let length): + if boxed { + buffer.appendInt32(1398007207) + } + serializeInt32(length, buffer: buffer, boxed: false) + break + case .sentCodeTypeFlashCall(let pattern): + if boxed { + buffer.appendInt32(-1425815847) + } + serializeString(pattern, buffer: buffer, boxed: false) + break + case .sentCodeTypeMissedCall(let prefix, let length): + if boxed { + buffer.appendInt32(-2113903484) + } + serializeString(prefix, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + break + case .sentCodeTypeSms(let length): + if boxed { + buffer.appendInt32(-1073693790) + } + serializeInt32(length, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .sentCodeTypeApp(let length): + return ("sentCodeTypeApp", [("length", String(describing: length))]) + case .sentCodeTypeCall(let length): + return ("sentCodeTypeCall", [("length", String(describing: length))]) + case .sentCodeTypeFlashCall(let pattern): + return ("sentCodeTypeFlashCall", [("pattern", String(describing: pattern))]) + case .sentCodeTypeMissedCall(let prefix, let length): + return ("sentCodeTypeMissedCall", [("prefix", String(describing: prefix)), ("length", String(describing: length))]) + case .sentCodeTypeSms(let length): + return ("sentCodeTypeSms", [("length", String(describing: length))]) + } + } + + public static func parse_sentCodeTypeApp(_ reader: BufferReader) -> SentCodeType? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.auth.SentCodeType.sentCodeTypeApp(length: _1!) + } + else { + return nil + } + } + public static func parse_sentCodeTypeCall(_ reader: BufferReader) -> SentCodeType? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.auth.SentCodeType.sentCodeTypeCall(length: _1!) + } + else { + return nil + } + } + public static func parse_sentCodeTypeFlashCall(_ reader: BufferReader) -> SentCodeType? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.auth.SentCodeType.sentCodeTypeFlashCall(pattern: _1!) + } + else { + return nil + } + } + public static func parse_sentCodeTypeMissedCall(_ reader: BufferReader) -> SentCodeType? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.auth.SentCodeType.sentCodeTypeMissedCall(prefix: _1!, length: _2!) + } + else { + return nil + } + } + public static func parse_sentCodeTypeSms(_ reader: BufferReader) -> SentCodeType? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.auth.SentCodeType.sentCodeTypeSms(length: _1!) + } + else { + return nil + } } } } -public extension Api.help { - enum PremiumPromo: TypeConstructorDescription { - case premiumPromo(statusText: String, statusEntities: [Api.MessageEntity], videoSections: [String], videos: [Api.Document], currency: String, monthlyAmount: Int64, users: [Api.User]) +public extension Api.channels { + enum AdminLogResults: TypeConstructorDescription { + case adminLogResults(events: [Api.ChannelAdminLogEvent], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let currency, let monthlyAmount, let users): + case .adminLogResults(let events, let chats, let users): if boxed { - buffer.appendInt32(-1974518743) + buffer.appendInt32(-309659827) } - serializeString(statusText, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(statusEntities.count)) - for item in statusEntities { + buffer.appendInt32(Int32(events.count)) + for item in events { item.serialize(buffer, true) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(videoSections.count)) - for item in videoSections { - serializeString(item, buffer: buffer, boxed: false) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(videos.count)) - for item in videos { + buffer.appendInt32(Int32(chats.count)) + for item in chats { item.serialize(buffer, true) } - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(monthlyAmount, buffer: buffer, boxed: false) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { @@ -249,43 +407,29 @@ public extension Api.help { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let currency, let monthlyAmount, let users): - return ("premiumPromo", [("statusText", String(describing: statusText)), ("statusEntities", String(describing: statusEntities)), ("videoSections", String(describing: videoSections)), ("videos", String(describing: videos)), ("currency", String(describing: currency)), ("monthlyAmount", String(describing: monthlyAmount)), ("users", String(describing: users))]) + case .adminLogResults(let events, let chats, let users): + return ("adminLogResults", [("events", String(describing: events)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_premiumPromo(_ reader: BufferReader) -> PremiumPromo? { - var _1: String? - _1 = parseString(reader) - var _2: [Api.MessageEntity]? + public static func parse_adminLogResults(_ reader: BufferReader) -> AdminLogResults? { + var _1: [Api.ChannelAdminLogEvent]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelAdminLogEvent.self) } - var _3: [String]? + var _2: [Api.Chat]? if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) } - var _4: [Api.Document]? + var _3: [Api.User]? if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - var _5: String? - _5 = parseString(reader) - var _6: Int64? - _6 = reader.readInt64() - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.help.PremiumPromo.premiumPromo(statusText: _1!, statusEntities: _2!, videoSections: _3!, videos: _4!, currency: _5!, monthlyAmount: _6!, users: _7!) + if _c1 && _c2 && _c3 { + return Api.channels.AdminLogResults.adminLogResults(events: _1!, chats: _2!, users: _3!) } else { return nil @@ -294,19 +438,538 @@ public extension Api.help { } } -public extension Api.help { - enum PromoData: TypeConstructorDescription { - case promoData(flags: Int32, expires: Int32, peer: Api.Peer, chats: [Api.Chat], users: [Api.User], psaType: String?, psaMessage: String?) - case promoDataEmpty(expires: Int32) +public extension Api.channels { + enum ChannelParticipant: TypeConstructorDescription { + case channelParticipant(participant: Api.ChannelParticipant, chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .promoData(let flags, let expires, let peer, let chats, let users, let psaType, let psaMessage): + case .channelParticipant(let participant, let chats, let users): if boxed { - buffer.appendInt32(-1942390465) + buffer.appendInt32(-541588713) + } + participant.serialize(buffer, true) + 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 .channelParticipant(let participant, let chats, let users): + return ("channelParticipant", [("participant", String(describing: participant)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_channelParticipant(_ reader: BufferReader) -> ChannelParticipant? { + var _1: Api.ChannelParticipant? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.ChannelParticipant + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.channels.ChannelParticipant.channelParticipant(participant: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.channels { + enum ChannelParticipants: TypeConstructorDescription { + case channelParticipants(count: Int32, participants: [Api.ChannelParticipant], chats: [Api.Chat], users: [Api.User]) + case channelParticipantsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .channelParticipants(let count, let participants, let chats, let users): + if boxed { + buffer.appendInt32(-1699676497) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(participants.count)) + for item in participants { + item.serialize(buffer, true) + } + 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 + case .channelParticipantsNotModified: + if boxed { + buffer.appendInt32(-266911767) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .channelParticipants(let count, let participants, let chats, let users): + return ("channelParticipants", [("count", String(describing: count)), ("participants", String(describing: participants)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .channelParticipantsNotModified: + return ("channelParticipantsNotModified", []) + } + } + + public static func parse_channelParticipants(_ reader: BufferReader) -> ChannelParticipants? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.ChannelParticipant]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelParticipant.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.channels.ChannelParticipants.channelParticipants(count: _1!, participants: _2!, chats: _3!, users: _4!) + } + else { + return nil + } + } + public static func parse_channelParticipantsNotModified(_ reader: BufferReader) -> ChannelParticipants? { + return Api.channels.ChannelParticipants.channelParticipantsNotModified + } + + } +} +public extension Api.channels { + enum SendAsPeers: TypeConstructorDescription { + case sendAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .sendAsPeers(let peers, let chats, let users): + if boxed { + buffer.appendInt32(-2091463255) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + item.serialize(buffer, true) + } + 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 .sendAsPeers(let peers, let chats, let users): + return ("sendAsPeers", [("peers", String(describing: peers)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_sendAsPeers(_ reader: BufferReader) -> SendAsPeers? { + var _1: [Api.Peer]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.channels.SendAsPeers.sendAsPeers(peers: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.contacts { + enum Blocked: TypeConstructorDescription { + case blocked(blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User]) + case blockedSlice(count: Int32, blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .blocked(let blocked, let chats, let users): + if boxed { + buffer.appendInt32(182326673) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(blocked.count)) + for item in blocked { + item.serialize(buffer, true) + } + 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 + case .blockedSlice(let count, let blocked, let chats, let users): + if boxed { + buffer.appendInt32(-513392236) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(blocked.count)) + for item in blocked { + item.serialize(buffer, true) + } + 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 .blocked(let blocked, let chats, let users): + return ("blocked", [("blocked", String(describing: blocked)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .blockedSlice(let count, let blocked, let chats, let users): + return ("blockedSlice", [("count", String(describing: count)), ("blocked", String(describing: blocked)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_blocked(_ reader: BufferReader) -> Blocked? { + var _1: [Api.PeerBlocked]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerBlocked.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.contacts.Blocked.blocked(blocked: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + public static func parse_blockedSlice(_ reader: BufferReader) -> Blocked? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.PeerBlocked]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PeerBlocked.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.contacts.Blocked.blockedSlice(count: _1!, blocked: _2!, chats: _3!, users: _4!) + } + else { + return nil + } + } + + } +} +public extension Api.contacts { + enum Contacts: TypeConstructorDescription { + case contacts(contacts: [Api.Contact], savedCount: Int32, users: [Api.User]) + case contactsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .contacts(let contacts, let savedCount, let users): + if boxed { + buffer.appendInt32(-353862078) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(contacts.count)) + for item in contacts { + item.serialize(buffer, true) + } + serializeInt32(savedCount, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + case .contactsNotModified: + if boxed { + buffer.appendInt32(-1219778094) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .contacts(let contacts, let savedCount, let users): + return ("contacts", [("contacts", String(describing: contacts)), ("savedCount", String(describing: savedCount)), ("users", String(describing: users))]) + case .contactsNotModified: + return ("contactsNotModified", []) + } + } + + public static func parse_contacts(_ reader: BufferReader) -> Contacts? { + var _1: [Api.Contact]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Contact.self) + } + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.contacts.Contacts.contacts(contacts: _1!, savedCount: _2!, users: _3!) + } + else { + return nil + } + } + public static func parse_contactsNotModified(_ reader: BufferReader) -> Contacts? { + return Api.contacts.Contacts.contactsNotModified + } + + } +} +public extension Api.contacts { + enum Found: TypeConstructorDescription { + case found(myResults: [Api.Peer], results: [Api.Peer], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .found(let myResults, let results, let chats, let users): + if boxed { + buffer.appendInt32(-1290580579) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(myResults.count)) + for item in myResults { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(results.count)) + for item in results { + item.serialize(buffer, true) + } + 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 .found(let myResults, let results, let chats, let users): + return ("found", [("myResults", String(describing: myResults)), ("results", String(describing: results)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_found(_ reader: BufferReader) -> Found? { + var _1: [Api.Peer]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + } + var _2: [Api.Peer]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.contacts.Found.found(myResults: _1!, results: _2!, chats: _3!, users: _4!) + } + else { + return nil + } + } + + } +} +public extension Api.contacts { + enum ImportedContacts: TypeConstructorDescription { + case importedContacts(imported: [Api.ImportedContact], popularInvites: [Api.PopularContact], retryContacts: [Int64], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .importedContacts(let imported, let popularInvites, let retryContacts, let users): + if boxed { + buffer.appendInt32(2010127419) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(imported.count)) + for item in imported { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(popularInvites.count)) + for item in popularInvites { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(retryContacts.count)) + for item in retryContacts { + serializeInt64(item, 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 .importedContacts(let imported, let popularInvites, let retryContacts, let users): + return ("importedContacts", [("imported", String(describing: imported)), ("popularInvites", String(describing: popularInvites)), ("retryContacts", String(describing: retryContacts)), ("users", String(describing: users))]) + } + } + + public static func parse_importedContacts(_ reader: BufferReader) -> ImportedContacts? { + var _1: [Api.ImportedContact]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ImportedContact.self) + } + var _2: [Api.PopularContact]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PopularContact.self) + } + var _3: [Int64]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.contacts.ImportedContacts.importedContacts(imported: _1!, popularInvites: _2!, retryContacts: _3!, users: _4!) + } + else { + return nil + } + } + + } +} +public extension Api.contacts { + enum ResolvedPeer: TypeConstructorDescription { + case resolvedPeer(peer: Api.Peer, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .resolvedPeer(let peer, let chats, let users): + if boxed { + buffer.appendInt32(2131196633) } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(expires, buffer: buffer, boxed: false) peer.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) @@ -318,48 +981,194 @@ public extension Api.help { for item in users { item.serialize(buffer, true) } - if Int(flags) & Int(1 << 1) != 0 {serializeString(psaType!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(psaMessage!, buffer: buffer, boxed: false)} - break - case .promoDataEmpty(let expires): - if boxed { - buffer.appendInt32(-1728664459) - } - serializeInt32(expires, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .promoData(let flags, let expires, let peer, let chats, let users, let psaType, let psaMessage): - return ("promoData", [("flags", String(describing: flags)), ("expires", String(describing: expires)), ("peer", String(describing: peer)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("psaType", String(describing: psaType)), ("psaMessage", String(describing: psaMessage))]) - case .promoDataEmpty(let expires): - return ("promoDataEmpty", [("expires", String(describing: expires))]) + case .resolvedPeer(let peer, let chats, let users): + return ("resolvedPeer", [("peer", String(describing: peer)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_promoData(_ reader: BufferReader) -> PromoData? { + public static func parse_resolvedPeer(_ reader: BufferReader) -> ResolvedPeer? { + var _1: Api.Peer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.contacts.ResolvedPeer.resolvedPeer(peer: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.contacts { + enum TopPeers: TypeConstructorDescription { + case topPeers(categories: [Api.TopPeerCategoryPeers], chats: [Api.Chat], users: [Api.User]) + case topPeersDisabled + case topPeersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .topPeers(let categories, let chats, let users): + if boxed { + buffer.appendInt32(1891070632) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(categories.count)) + for item in categories { + item.serialize(buffer, true) + } + 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 + case .topPeersDisabled: + if boxed { + buffer.appendInt32(-1255369827) + } + + break + case .topPeersNotModified: + if boxed { + buffer.appendInt32(-567906571) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .topPeers(let categories, let chats, let users): + return ("topPeers", [("categories", String(describing: categories)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .topPeersDisabled: + return ("topPeersDisabled", []) + case .topPeersNotModified: + return ("topPeersNotModified", []) + } + } + + public static func parse_topPeers(_ reader: BufferReader) -> TopPeers? { + var _1: [Api.TopPeerCategoryPeers]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.TopPeerCategoryPeers.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.contacts.TopPeers.topPeers(categories: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + public static func parse_topPeersDisabled(_ reader: BufferReader) -> TopPeers? { + return Api.contacts.TopPeers.topPeersDisabled + } + public static func parse_topPeersNotModified(_ reader: BufferReader) -> TopPeers? { + return Api.contacts.TopPeers.topPeersNotModified + } + + } +} +public extension Api.help { + enum AppUpdate: TypeConstructorDescription { + case appUpdate(flags: Int32, id: Int32, version: String, text: String, entities: [Api.MessageEntity], document: Api.Document?, url: String?, sticker: Api.Document?) + case noAppUpdate + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .appUpdate(let flags, let id, let version, let text, let entities, let document, let url, let sticker): + if boxed { + buffer.appendInt32(-860107216) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeString(version, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 1) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {sticker!.serialize(buffer, true)} + break + case .noAppUpdate: + if boxed { + buffer.appendInt32(-1000708810) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .appUpdate(let flags, let id, let version, let text, let entities, let document, let url, let sticker): + return ("appUpdate", [("flags", String(describing: flags)), ("id", String(describing: id)), ("version", String(describing: version)), ("text", String(describing: text)), ("entities", String(describing: entities)), ("document", String(describing: document)), ("url", String(describing: url)), ("sticker", String(describing: sticker))]) + case .noAppUpdate: + return ("noAppUpdate", []) + } + } + + public static func parse_appUpdate(_ reader: BufferReader) -> AppUpdate? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: Api.Peer? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _4: [Api.Chat]? + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: [Api.MessageEntity]? if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) } - var _5: [Api.User]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _6: String? - if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } + var _6: Api.Document? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.Document + } } var _7: String? if Int(_1!) & Int(1 << 2) != 0 {_7 = parseString(reader) } + var _8: Api.Document? + if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.Document + } } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -367,618 +1176,41 @@ public extension Api.help { let _c5 = _5 != nil let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.help.PromoData.promoData(flags: _1!, expires: _2!, peer: _3!, chats: _4!, users: _5!, psaType: _6, psaMessage: _7) + let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.help.AppUpdate.appUpdate(flags: _1!, id: _2!, version: _3!, text: _4!, entities: _5!, document: _6, url: _7, sticker: _8) } else { return nil } } - public static func parse_promoDataEmpty(_ reader: BufferReader) -> PromoData? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.help.PromoData.promoDataEmpty(expires: _1!) - } - else { - return nil - } + public static func parse_noAppUpdate(_ reader: BufferReader) -> AppUpdate? { + return Api.help.AppUpdate.noAppUpdate } } } public extension Api.help { - enum RecentMeUrls: TypeConstructorDescription { - case recentMeUrls(urls: [Api.RecentMeUrl], chats: [Api.Chat], users: [Api.User]) + enum CountriesList: TypeConstructorDescription { + case countriesList(countries: [Api.help.Country], hash: Int32) + case countriesListNotModified public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .recentMeUrls(let urls, let chats, let users): + case .countriesList(let countries, let hash): if boxed { - buffer.appendInt32(235081943) + buffer.appendInt32(-2016381538) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(urls.count)) - for item in urls { + buffer.appendInt32(Int32(countries.count)) + for item in countries { item.serialize(buffer, true) } - 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 .recentMeUrls(let urls, let chats, let users): - return ("recentMeUrls", [("urls", String(describing: urls)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_recentMeUrls(_ reader: BufferReader) -> RecentMeUrls? { - var _1: [Api.RecentMeUrl]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RecentMeUrl.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.help.RecentMeUrls.recentMeUrls(urls: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.help { - enum Support: TypeConstructorDescription { - case support(phoneNumber: String, user: Api.User) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .support(let phoneNumber, let user): - if boxed { - buffer.appendInt32(398898678) - } - serializeString(phoneNumber, buffer: buffer, boxed: false) - user.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .support(let phoneNumber, let user): - return ("support", [("phoneNumber", String(describing: phoneNumber)), ("user", String(describing: user))]) - } - } - - public static func parse_support(_ reader: BufferReader) -> Support? { - var _1: String? - _1 = parseString(reader) - var _2: Api.User? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.User - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.help.Support.support(phoneNumber: _1!, user: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.help { - enum SupportName: TypeConstructorDescription { - case supportName(name: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .supportName(let name): - if boxed { - buffer.appendInt32(-1945767479) - } - serializeString(name, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .supportName(let name): - return ("supportName", [("name", String(describing: name))]) - } - } - - public static func parse_supportName(_ reader: BufferReader) -> SupportName? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.help.SupportName.supportName(name: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.help { - enum TermsOfService: TypeConstructorDescription { - case termsOfService(flags: Int32, id: Api.DataJSON, text: String, entities: [Api.MessageEntity], minAgeConfirm: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .termsOfService(let flags, let id, let text, let entities, let minAgeConfirm): - if boxed { - buffer.appendInt32(2013922064) - } - serializeInt32(flags, buffer: buffer, boxed: false) - id.serialize(buffer, true) - serializeString(text, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities.count)) - for item in entities { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(minAgeConfirm!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .termsOfService(let flags, let id, let text, let entities, let minAgeConfirm): - return ("termsOfService", [("flags", String(describing: flags)), ("id", String(describing: id)), ("text", String(describing: text)), ("entities", String(describing: entities)), ("minAgeConfirm", String(describing: minAgeConfirm))]) - } - } - - public static func parse_termsOfService(_ reader: BufferReader) -> TermsOfService? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.DataJSON? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.DataJSON - } - var _3: String? - _3 = parseString(reader) - var _4: [Api.MessageEntity]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } - var _5: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.help.TermsOfService.termsOfService(flags: _1!, id: _2!, text: _3!, entities: _4!, minAgeConfirm: _5) - } - else { - return nil - } - } - - } -} -public extension Api.help { - enum TermsOfServiceUpdate: TypeConstructorDescription { - case termsOfServiceUpdate(expires: Int32, termsOfService: Api.help.TermsOfService) - case termsOfServiceUpdateEmpty(expires: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .termsOfServiceUpdate(let expires, let termsOfService): - if boxed { - buffer.appendInt32(686618977) - } - serializeInt32(expires, buffer: buffer, boxed: false) - termsOfService.serialize(buffer, true) - break - case .termsOfServiceUpdateEmpty(let expires): - if boxed { - buffer.appendInt32(-483352705) - } - serializeInt32(expires, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .termsOfServiceUpdate(let expires, let termsOfService): - return ("termsOfServiceUpdate", [("expires", String(describing: expires)), ("termsOfService", String(describing: termsOfService))]) - case .termsOfServiceUpdateEmpty(let expires): - return ("termsOfServiceUpdateEmpty", [("expires", String(describing: expires))]) - } - } - - public static func parse_termsOfServiceUpdate(_ reader: BufferReader) -> TermsOfServiceUpdate? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.help.TermsOfService? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.help.TermsOfService - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.help.TermsOfServiceUpdate.termsOfServiceUpdate(expires: _1!, termsOfService: _2!) - } - else { - return nil - } - } - public static func parse_termsOfServiceUpdateEmpty(_ reader: BufferReader) -> TermsOfServiceUpdate? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.help.TermsOfServiceUpdate.termsOfServiceUpdateEmpty(expires: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.help { - enum UserInfo: TypeConstructorDescription { - case userInfo(message: String, entities: [Api.MessageEntity], author: String, date: Int32) - case userInfoEmpty - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .userInfo(let message, let entities, let author, let date): - if boxed { - buffer.appendInt32(32192344) - } - serializeString(message, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities.count)) - for item in entities { - item.serialize(buffer, true) - } - serializeString(author, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - break - case .userInfoEmpty: - if boxed { - buffer.appendInt32(-206688531) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .userInfo(let message, let entities, let author, let date): - return ("userInfo", [("message", String(describing: message)), ("entities", String(describing: entities)), ("author", String(describing: author)), ("date", String(describing: date))]) - case .userInfoEmpty: - return ("userInfoEmpty", []) - } - } - - public static func parse_userInfo(_ reader: BufferReader) -> UserInfo? { - var _1: String? - _1 = parseString(reader) - var _2: [Api.MessageEntity]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } - var _3: String? - _3 = parseString(reader) - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.help.UserInfo.userInfo(message: _1!, entities: _2!, author: _3!, date: _4!) - } - else { - return nil - } - } - public static func parse_userInfoEmpty(_ reader: BufferReader) -> UserInfo? { - return Api.help.UserInfo.userInfoEmpty - } - - } -} -public extension Api.messages { - enum AffectedFoundMessages: TypeConstructorDescription { - case affectedFoundMessages(pts: Int32, ptsCount: Int32, offset: Int32, messages: [Int32]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .affectedFoundMessages(let pts, let ptsCount, let offset, let messages): - if boxed { - buffer.appendInt32(-275956116) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - serializeInt32(offset, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - serializeInt32(item, buffer: buffer, boxed: false) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .affectedFoundMessages(let pts, let ptsCount, let offset, let messages): - return ("affectedFoundMessages", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("offset", String(describing: offset)), ("messages", String(describing: messages))]) - } - } - - public static func parse_affectedFoundMessages(_ reader: BufferReader) -> AffectedFoundMessages? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: [Int32]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.messages.AffectedFoundMessages.affectedFoundMessages(pts: _1!, ptsCount: _2!, offset: _3!, messages: _4!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum AffectedHistory: TypeConstructorDescription { - case affectedHistory(pts: Int32, ptsCount: Int32, offset: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .affectedHistory(let pts, let ptsCount, let offset): - if boxed { - buffer.appendInt32(-1269012015) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - serializeInt32(offset, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .affectedHistory(let pts, let ptsCount, let offset): - return ("affectedHistory", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("offset", String(describing: offset))]) - } - } - - public static func parse_affectedHistory(_ reader: BufferReader) -> AffectedHistory? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.AffectedHistory.affectedHistory(pts: _1!, ptsCount: _2!, offset: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum AffectedMessages: TypeConstructorDescription { - case affectedMessages(pts: Int32, ptsCount: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .affectedMessages(let pts, let ptsCount): - if boxed { - buffer.appendInt32(-2066640507) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .affectedMessages(let pts, let ptsCount): - return ("affectedMessages", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) - } - } - - public static func parse_affectedMessages(_ reader: BufferReader) -> AffectedMessages? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.AffectedMessages.affectedMessages(pts: _1!, ptsCount: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum AllStickers: TypeConstructorDescription { - case allStickers(hash: Int64, sets: [Api.StickerSet]) - case allStickersNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .allStickers(let hash, let sets): - if boxed { - buffer.appendInt32(-843329861) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sets.count)) - for item in sets { - item.serialize(buffer, true) - } - break - case .allStickersNotModified: - if boxed { - buffer.appendInt32(-395967805) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .allStickers(let hash, let sets): - return ("allStickers", [("hash", String(describing: hash)), ("sets", String(describing: sets))]) - case .allStickersNotModified: - return ("allStickersNotModified", []) - } - } - - public static func parse_allStickers(_ reader: BufferReader) -> AllStickers? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.StickerSet]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSet.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.AllStickers.allStickers(hash: _1!, sets: _2!) - } - else { - return nil - } - } - public static func parse_allStickersNotModified(_ reader: BufferReader) -> AllStickers? { - return Api.messages.AllStickers.allStickersNotModified - } - - } -} -public extension Api.messages { - enum ArchivedStickers: TypeConstructorDescription { - case archivedStickers(count: Int32, sets: [Api.StickerSetCovered]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .archivedStickers(let count, let sets): - if boxed { - buffer.appendInt32(1338747336) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sets.count)) - for item in sets { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .archivedStickers(let count, let sets): - return ("archivedStickers", [("count", String(describing: count)), ("sets", String(describing: sets))]) - } - } - - public static func parse_archivedStickers(_ reader: BufferReader) -> ArchivedStickers? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.StickerSetCovered]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.ArchivedStickers.archivedStickers(count: _1!, sets: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum AvailableReactions: TypeConstructorDescription { - case availableReactions(hash: Int32, reactions: [Api.AvailableReaction]) - case availableReactionsNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .availableReactions(let hash, let reactions): - if boxed { - buffer.appendInt32(1989032621) - } serializeInt32(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(reactions.count)) - for item in reactions { - item.serialize(buffer, true) - } break - case .availableReactionsNotModified: + case .countriesListNotModified: if boxed { - buffer.appendInt32(-1626924713) + buffer.appendInt32(-1815339214) } break @@ -987,387 +1219,85 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .availableReactions(let hash, let reactions): - return ("availableReactions", [("hash", String(describing: hash)), ("reactions", String(describing: reactions))]) - case .availableReactionsNotModified: - return ("availableReactionsNotModified", []) + case .countriesList(let countries, let hash): + return ("countriesList", [("countries", String(describing: countries)), ("hash", String(describing: hash))]) + case .countriesListNotModified: + return ("countriesListNotModified", []) } } - public static func parse_availableReactions(_ reader: BufferReader) -> AvailableReactions? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.AvailableReaction]? + public static func parse_countriesList(_ reader: BufferReader) -> CountriesList? { + var _1: [Api.help.Country]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AvailableReaction.self) + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.Country.self) } + var _2: Int32? + _2 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.messages.AvailableReactions.availableReactions(hash: _1!, reactions: _2!) + return Api.help.CountriesList.countriesList(countries: _1!, hash: _2!) } else { return nil } } - public static func parse_availableReactionsNotModified(_ reader: BufferReader) -> AvailableReactions? { - return Api.messages.AvailableReactions.availableReactionsNotModified + public static func parse_countriesListNotModified(_ reader: BufferReader) -> CountriesList? { + return Api.help.CountriesList.countriesListNotModified } } } -public extension Api.messages { - enum BotCallbackAnswer: TypeConstructorDescription { - case botCallbackAnswer(flags: Int32, message: String?, url: String?, cacheTime: Int32) +public extension Api.help { + enum Country: TypeConstructorDescription { + case country(flags: Int32, iso2: String, defaultName: String, name: String?, countryCodes: [Api.help.CountryCode]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .botCallbackAnswer(let flags, let message, let url, let cacheTime): + case .country(let flags, let iso2, let defaultName, let name, let countryCodes): if boxed { - buffer.appendInt32(911761060) + buffer.appendInt32(-1014526429) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(message!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - serializeInt32(cacheTime, buffer: buffer, boxed: false) + serializeString(iso2, buffer: buffer, boxed: false) + serializeString(defaultName, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeString(name!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(countryCodes.count)) + for item in countryCodes { + item.serialize(buffer, true) + } break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .botCallbackAnswer(let flags, let message, let url, let cacheTime): - return ("botCallbackAnswer", [("flags", String(describing: flags)), ("message", String(describing: message)), ("url", String(describing: url)), ("cacheTime", String(describing: cacheTime))]) + case .country(let flags, let iso2, let defaultName, let name, let countryCodes): + return ("country", [("flags", String(describing: flags)), ("iso2", String(describing: iso2)), ("defaultName", String(describing: defaultName)), ("name", String(describing: name)), ("countryCodes", String(describing: countryCodes))]) } } - public static func parse_botCallbackAnswer(_ reader: BufferReader) -> BotCallbackAnswer? { + public static func parse_country(_ reader: BufferReader) -> Country? { var _1: Int32? _1 = reader.readInt32() var _2: String? - if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + _2 = parseString(reader) var _3: String? - if Int(_1!) & Int(1 << 2) != 0 {_3 = parseString(reader) } - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.messages.BotCallbackAnswer.botCallbackAnswer(flags: _1!, message: _2, url: _3, cacheTime: _4!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum BotResults: TypeConstructorDescription { - case botResults(flags: Int32, queryId: Int64, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?, results: [Api.BotInlineResult], cacheTime: Int32, users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime, let users): - if boxed { - buffer.appendInt32(-1803769784) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {switchPm!.serialize(buffer, true)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(results.count)) - for item in results { - item.serialize(buffer, true) - } - serializeInt32(cacheTime, 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 .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime, let users): - return ("botResults", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("nextOffset", String(describing: nextOffset)), ("switchPm", String(describing: switchPm)), ("results", String(describing: results)), ("cacheTime", String(describing: cacheTime)), ("users", String(describing: users))]) - } - } - - public static func parse_botResults(_ reader: BufferReader) -> BotResults? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: String? - if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } - var _4: Api.InlineBotSwitchPM? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.InlineBotSwitchPM - } } - var _5: [Api.BotInlineResult]? + _3 = parseString(reader) + var _4: String? + if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) } + var _5: [Api.help.CountryCode]? if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInlineResult.self) - } - var _6: Int32? - _6 = reader.readInt32() - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.help.CountryCode.self) } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.messages.BotResults.botResults(flags: _1!, queryId: _2!, nextOffset: _3, switchPm: _4, results: _5!, cacheTime: _6!, users: _7!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum ChatAdminsWithInvites: TypeConstructorDescription { - case chatAdminsWithInvites(admins: [Api.ChatAdminWithInvites], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .chatAdminsWithInvites(let admins, let users): - if boxed { - buffer.appendInt32(-1231326505) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(admins.count)) - for item in admins { - 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 .chatAdminsWithInvites(let admins, let users): - return ("chatAdminsWithInvites", [("admins", String(describing: admins)), ("users", String(describing: users))]) - } - } - - public static func parse_chatAdminsWithInvites(_ reader: BufferReader) -> ChatAdminsWithInvites? { - var _1: [Api.ChatAdminWithInvites]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChatAdminWithInvites.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.ChatAdminsWithInvites.chatAdminsWithInvites(admins: _1!, users: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum ChatFull: TypeConstructorDescription { - case chatFull(fullChat: Api.ChatFull, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .chatFull(let fullChat, let chats, let users): - if boxed { - buffer.appendInt32(-438840932) - } - fullChat.serialize(buffer, true) - 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 .chatFull(let fullChat, let chats, let users): - return ("chatFull", [("fullChat", String(describing: fullChat)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_chatFull(_ reader: BufferReader) -> ChatFull? { - var _1: Api.ChatFull? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.ChatFull - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.ChatFull.chatFull(fullChat: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum ChatInviteImporters: TypeConstructorDescription { - case chatInviteImporters(count: Int32, importers: [Api.ChatInviteImporter], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .chatInviteImporters(let count, let importers, let users): - if boxed { - buffer.appendInt32(-2118733814) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(importers.count)) - for item in importers { - 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 .chatInviteImporters(let count, let importers, let users): - return ("chatInviteImporters", [("count", String(describing: count)), ("importers", String(describing: importers)), ("users", String(describing: users))]) - } - } - - public static func parse_chatInviteImporters(_ reader: BufferReader) -> ChatInviteImporters? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.ChatInviteImporter]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChatInviteImporter.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.ChatInviteImporters.chatInviteImporters(count: _1!, importers: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum Chats: TypeConstructorDescription { - case chats(chats: [Api.Chat]) - case chatsSlice(count: Int32, chats: [Api.Chat]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .chats(let chats): - if boxed { - buffer.appendInt32(1694474197) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - break - case .chatsSlice(let count, let chats): - if boxed { - buffer.appendInt32(-1663561404) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .chats(let chats): - return ("chats", [("chats", String(describing: chats))]) - case .chatsSlice(let count, let chats): - return ("chatsSlice", [("count", String(describing: count)), ("chats", String(describing: chats))]) - } - } - - public static func parse_chats(_ reader: BufferReader) -> Chats? { - var _1: [Api.Chat]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.messages.Chats.chats(chats: _1!) - } - else { - return nil - } - } - public static func parse_chatsSlice(_ reader: BufferReader) -> Chats? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.Chats.chatsSlice(count: _1!, chats: _2!) + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.help.Country.country(flags: _1!, iso2: _2!, defaultName: _3!, name: _4, countryCodes: _5!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api24.swift b/submodules/TelegramApi/Sources/Api24.swift index 8d01ba6f9e..706f76027d 100644 --- a/submodules/TelegramApi/Sources/Api24.swift +++ b/submodules/TelegramApi/Sources/Api24.swift @@ -1,333 +1,55 @@ -public extension Api.messages { - enum CheckedHistoryImportPeer: TypeConstructorDescription { - case checkedHistoryImportPeer(confirmText: String) +public extension Api.help { + enum CountryCode: TypeConstructorDescription { + case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .checkedHistoryImportPeer(let confirmText): + case .countryCode(let flags, let countryCode, let prefixes, let patterns): if boxed { - buffer.appendInt32(-1571952873) - } - serializeString(confirmText, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .checkedHistoryImportPeer(let confirmText): - return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))]) - } - } - - public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum DhConfig: TypeConstructorDescription { - case dhConfig(g: Int32, p: Buffer, version: Int32, random: Buffer) - case dhConfigNotModified(random: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .dhConfig(let g, let p, let version, let random): - if boxed { - buffer.appendInt32(740433629) - } - serializeInt32(g, buffer: buffer, boxed: false) - serializeBytes(p, buffer: buffer, boxed: false) - serializeInt32(version, buffer: buffer, boxed: false) - serializeBytes(random, buffer: buffer, boxed: false) - break - case .dhConfigNotModified(let random): - if boxed { - buffer.appendInt32(-1058912715) - } - serializeBytes(random, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .dhConfig(let g, let p, let version, let random): - return ("dhConfig", [("g", String(describing: g)), ("p", String(describing: p)), ("version", String(describing: version)), ("random", String(describing: random))]) - case .dhConfigNotModified(let random): - return ("dhConfigNotModified", [("random", String(describing: random))]) - } - } - - public static func parse_dhConfig(_ reader: BufferReader) -> DhConfig? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Int32? - _3 = reader.readInt32() - var _4: Buffer? - _4 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.messages.DhConfig.dhConfig(g: _1!, p: _2!, version: _3!, random: _4!) - } - else { - return nil - } - } - public static func parse_dhConfigNotModified(_ reader: BufferReader) -> DhConfig? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.messages.DhConfig.dhConfigNotModified(random: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum Dialogs: TypeConstructorDescription { - case dialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - case dialogsNotModified(count: Int32) - case dialogsSlice(count: Int32, dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .dialogs(let dialogs, let messages, let chats, let users): - if boxed { - buffer.appendInt32(364538944) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dialogs.count)) - for item in dialogs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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 - case .dialogsNotModified(let count): - if boxed { - buffer.appendInt32(-253500010) - } - serializeInt32(count, buffer: buffer, boxed: false) - break - case .dialogsSlice(let count, let dialogs, let messages, let chats, let users): - if boxed { - buffer.appendInt32(1910543603) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dialogs.count)) - for item in dialogs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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 .dialogs(let dialogs, let messages, let chats, let users): - return ("dialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .dialogsNotModified(let count): - return ("dialogsNotModified", [("count", String(describing: count))]) - case .dialogsSlice(let count, let dialogs, let messages, let chats, let users): - return ("dialogsSlice", [("count", String(describing: count)), ("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_dialogs(_ reader: BufferReader) -> Dialogs? { - var _1: [Api.Dialog]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) - } - var _2: [Api.Message]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.messages.Dialogs.dialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!) - } - else { - return nil - } - } - public static func parse_dialogsNotModified(_ reader: BufferReader) -> Dialogs? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.messages.Dialogs.dialogsNotModified(count: _1!) - } - else { - return nil - } - } - public static func parse_dialogsSlice(_ reader: BufferReader) -> Dialogs? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.Dialog]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) - } - var _3: [Api.Message]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _4: [Api.Chat]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - 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 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.Dialogs.dialogsSlice(count: _1!, dialogs: _2!, messages: _3!, chats: _4!, users: _5!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum DiscussionMessage: TypeConstructorDescription { - case discussionMessage(flags: Int32, messages: [Api.Message], maxId: Int32?, readInboxMaxId: Int32?, readOutboxMaxId: Int32?, unreadCount: Int32, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users): - if boxed { - buffer.appendInt32(-1506535550) + buffer.appendInt32(1107543535) } serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(readInboxMaxId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(readOutboxMaxId!, buffer: buffer, boxed: false)} - serializeInt32(unreadCount, 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) - } + serializeString(countryCode, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prefixes!.count)) + for item in prefixes! { + serializeString(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(patterns!.count)) + for item in patterns! { + serializeString(item, buffer: buffer, boxed: false) + }} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users): - return ("discussionMessage", [("flags", String(describing: flags)), ("messages", String(describing: messages)), ("maxId", String(describing: maxId)), ("readInboxMaxId", String(describing: readInboxMaxId)), ("readOutboxMaxId", String(describing: readOutboxMaxId)), ("unreadCount", String(describing: unreadCount)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .countryCode(let flags, let countryCode, let prefixes, let patterns): + return ("countryCode", [("flags", String(describing: flags)), ("countryCode", String(describing: countryCode)), ("prefixes", String(describing: prefixes)), ("patterns", String(describing: patterns))]) } } - public static func parse_discussionMessage(_ reader: BufferReader) -> DiscussionMessage? { + public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? { var _1: Int32? _1 = reader.readInt32() - var _2: [Api.Message]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - var _4: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } - var _5: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } - var _6: Int32? - _6 = reader.readInt32() - var _7: [Api.Chat]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _8: [Api.User]? - if let _ = reader.readInt32() { - _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } + var _2: String? + _2 = parseString(reader) + var _3: [String]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } } + var _4: [String]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { - return Api.messages.DiscussionMessage.discussionMessage(flags: _1!, messages: _2!, maxId: _3, readInboxMaxId: _4, readOutboxMaxId: _5, unreadCount: _6!, chats: _7!, users: _8!) + if _c1 && _c2 && _c3 && _c4 { + return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4) } else { return nil @@ -336,174 +58,28 @@ public extension Api.messages { } } -public extension Api.messages { - enum ExportedChatInvite: TypeConstructorDescription { - case exportedChatInvite(invite: Api.ExportedChatInvite, users: [Api.User]) - case exportedChatInviteReplaced(invite: Api.ExportedChatInvite, newInvite: Api.ExportedChatInvite, users: [Api.User]) +public extension Api.help { + enum DeepLinkInfo: TypeConstructorDescription { + case deepLinkInfo(flags: Int32, message: String, entities: [Api.MessageEntity]?) + case deepLinkInfoEmpty public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .exportedChatInvite(let invite, let users): + case .deepLinkInfo(let flags, let message, let entities): if boxed { - buffer.appendInt32(410107472) + buffer.appendInt32(1783556146) } - invite.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { item.serialize(buffer, true) - } + }} break - case .exportedChatInviteReplaced(let invite, let newInvite, let users): + case .deepLinkInfoEmpty: if boxed { - buffer.appendInt32(572915951) - } - invite.serialize(buffer, true) - newInvite.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 .exportedChatInvite(let invite, let users): - return ("exportedChatInvite", [("invite", String(describing: invite)), ("users", String(describing: users))]) - case .exportedChatInviteReplaced(let invite, let newInvite, let users): - return ("exportedChatInviteReplaced", [("invite", String(describing: invite)), ("newInvite", String(describing: newInvite)), ("users", String(describing: users))]) - } - } - - public static func parse_exportedChatInvite(_ reader: BufferReader) -> ExportedChatInvite? { - var _1: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.ExportedChatInvite.exportedChatInvite(invite: _1!, users: _2!) - } - else { - return nil - } - } - public static func parse_exportedChatInviteReplaced(_ reader: BufferReader) -> ExportedChatInvite? { - var _1: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - var _2: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.ExportedChatInvite.exportedChatInviteReplaced(invite: _1!, newInvite: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum ExportedChatInvites: TypeConstructorDescription { - case exportedChatInvites(count: Int32, invites: [Api.ExportedChatInvite], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .exportedChatInvites(let count, let invites, let users): - if boxed { - buffer.appendInt32(-1111085620) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(invites.count)) - for item in invites { - 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 .exportedChatInvites(let count, let invites, let users): - return ("exportedChatInvites", [("count", String(describing: count)), ("invites", String(describing: invites)), ("users", String(describing: users))]) - } - } - - public static func parse_exportedChatInvites(_ reader: BufferReader) -> ExportedChatInvites? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.ExportedChatInvite]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ExportedChatInvite.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.ExportedChatInvites.exportedChatInvites(count: _1!, invites: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum FavedStickers: TypeConstructorDescription { - case favedStickers(hash: Int64, packs: [Api.StickerPack], stickers: [Api.Document]) - case favedStickersNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .favedStickers(let hash, let packs, let stickers): - if boxed { - buffer.appendInt32(750063767) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(packs.count)) - for item in packs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stickers.count)) - for item in stickers { - item.serialize(buffer, true) - } - break - case .favedStickersNotModified: - if boxed { - buffer.appendInt32(-1634752813) + buffer.appendInt32(1722786150) } break @@ -512,116 +88,204 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .favedStickers(let hash, let packs, let stickers): - return ("favedStickers", [("hash", String(describing: hash)), ("packs", String(describing: packs)), ("stickers", String(describing: stickers))]) - case .favedStickersNotModified: - return ("favedStickersNotModified", []) + case .deepLinkInfo(let flags, let message, let entities): + return ("deepLinkInfo", [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))]) + case .deepLinkInfoEmpty: + return ("deepLinkInfoEmpty", []) } } - public static func parse_favedStickers(_ reader: BufferReader) -> FavedStickers? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.StickerPack]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) - } - var _3: [Api.Document]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } + public static func parse_deepLinkInfo(_ reader: BufferReader) -> DeepLinkInfo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil if _c1 && _c2 && _c3 { - return Api.messages.FavedStickers.favedStickers(hash: _1!, packs: _2!, stickers: _3!) + return Api.help.DeepLinkInfo.deepLinkInfo(flags: _1!, message: _2!, entities: _3) } else { return nil } } - public static func parse_favedStickersNotModified(_ reader: BufferReader) -> FavedStickers? { - return Api.messages.FavedStickers.favedStickersNotModified + public static func parse_deepLinkInfoEmpty(_ reader: BufferReader) -> DeepLinkInfo? { + return Api.help.DeepLinkInfo.deepLinkInfoEmpty } } } -public extension Api.messages { - enum FeaturedStickers: TypeConstructorDescription { - case featuredStickers(flags: Int32, hash: Int64, count: Int32, sets: [Api.StickerSetCovered], unread: [Int64]) - case featuredStickersNotModified(count: Int32) +public extension Api.help { + enum InviteText: TypeConstructorDescription { + case inviteText(message: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .featuredStickers(let flags, let hash, let count, let sets, let unread): + case .inviteText(let message): if boxed { - buffer.appendInt32(-1103615738) + buffer.appendInt32(415997816) } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sets.count)) - for item in sets { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(unread.count)) - for item in unread { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .featuredStickersNotModified(let count): - if boxed { - buffer.appendInt32(-958657434) - } - serializeInt32(count, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .featuredStickers(let flags, let hash, let count, let sets, let unread): - return ("featuredStickers", [("flags", String(describing: flags)), ("hash", String(describing: hash)), ("count", String(describing: count)), ("sets", String(describing: sets)), ("unread", String(describing: unread))]) - case .featuredStickersNotModified(let count): - return ("featuredStickersNotModified", [("count", String(describing: count))]) + case .inviteText(let message): + return ("inviteText", [("message", String(describing: message))]) } } - public static func parse_featuredStickers(_ reader: BufferReader) -> FeaturedStickers? { + public static func parse_inviteText(_ reader: BufferReader) -> InviteText? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.help.InviteText.inviteText(message: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.help { + enum PassportConfig: TypeConstructorDescription { + case passportConfig(hash: Int32, countriesLangs: Api.DataJSON) + case passportConfigNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .passportConfig(let hash, let countriesLangs): + if boxed { + buffer.appendInt32(-1600596305) + } + serializeInt32(hash, buffer: buffer, boxed: false) + countriesLangs.serialize(buffer, true) + break + case .passportConfigNotModified: + if boxed { + buffer.appendInt32(-1078332329) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .passportConfig(let hash, let countriesLangs): + return ("passportConfig", [("hash", String(describing: hash)), ("countriesLangs", String(describing: countriesLangs))]) + case .passportConfigNotModified: + return ("passportConfigNotModified", []) + } + } + + public static func parse_passportConfig(_ reader: BufferReader) -> PassportConfig? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - var _4: [Api.StickerSetCovered]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + var _2: Api.DataJSON? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DataJSON } - var _5: [Int64]? + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.help.PassportConfig.passportConfig(hash: _1!, countriesLangs: _2!) + } + else { + return nil + } + } + public static func parse_passportConfigNotModified(_ reader: BufferReader) -> PassportConfig? { + return Api.help.PassportConfig.passportConfigNotModified + } + + } +} +public extension Api.help { + enum PremiumPromo: TypeConstructorDescription { + case premiumPromo(statusText: String, statusEntities: [Api.MessageEntity], videoSections: [String], videos: [Api.Document], currency: String, monthlyAmount: Int64, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let currency, let monthlyAmount, let users): + if boxed { + buffer.appendInt32(-1974518743) + } + serializeString(statusText, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(statusEntities.count)) + for item in statusEntities { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(videoSections.count)) + for item in videoSections { + serializeString(item, buffer: buffer, boxed: false) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(videos.count)) + for item in videos { + item.serialize(buffer, true) + } + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(monthlyAmount, 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 .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let currency, let monthlyAmount, let users): + return ("premiumPromo", [("statusText", String(describing: statusText)), ("statusEntities", String(describing: statusEntities)), ("videoSections", String(describing: videoSections)), ("videos", String(describing: videos)), ("currency", String(describing: currency)), ("monthlyAmount", String(describing: monthlyAmount)), ("users", String(describing: users))]) + } + } + + public static func parse_premiumPromo(_ reader: BufferReader) -> PremiumPromo? { + var _1: String? + _1 = parseString(reader) + var _2: [Api.MessageEntity]? if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } + var _3: [String]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } + var _4: [Api.Document]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + var _5: String? + _5 = parseString(reader) + var _6: Int64? + _6 = reader.readInt64() + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.FeaturedStickers.featuredStickers(flags: _1!, hash: _2!, count: _3!, sets: _4!, unread: _5!) - } - else { - return nil - } - } - public static func parse_featuredStickersNotModified(_ reader: BufferReader) -> FeaturedStickers? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.messages.FeaturedStickers.featuredStickersNotModified(count: _1!) + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.help.PremiumPromo.premiumPromo(statusText: _1!, statusEntities: _2!, videoSections: _3!, videos: _4!, currency: _5!, monthlyAmount: _6!, users: _7!) } else { return nil @@ -630,207 +294,20 @@ public extension Api.messages { } } -public extension Api.messages { - enum FoundStickerSets: TypeConstructorDescription { - case foundStickerSets(hash: Int64, sets: [Api.StickerSetCovered]) - case foundStickerSetsNotModified +public extension Api.help { + enum PromoData: TypeConstructorDescription { + case promoData(flags: Int32, expires: Int32, peer: Api.Peer, chats: [Api.Chat], users: [Api.User], psaType: String?, psaMessage: String?) + case promoDataEmpty(expires: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .foundStickerSets(let hash, let sets): + case .promoData(let flags, let expires, let peer, let chats, let users, let psaType, let psaMessage): if boxed { - buffer.appendInt32(-1963942446) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sets.count)) - for item in sets { - item.serialize(buffer, true) - } - break - case .foundStickerSetsNotModified: - if boxed { - buffer.appendInt32(223655517) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .foundStickerSets(let hash, let sets): - return ("foundStickerSets", [("hash", String(describing: hash)), ("sets", String(describing: sets))]) - case .foundStickerSetsNotModified: - return ("foundStickerSetsNotModified", []) - } - } - - public static func parse_foundStickerSets(_ reader: BufferReader) -> FoundStickerSets? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.StickerSetCovered]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.FoundStickerSets.foundStickerSets(hash: _1!, sets: _2!) - } - else { - return nil - } - } - public static func parse_foundStickerSetsNotModified(_ reader: BufferReader) -> FoundStickerSets? { - return Api.messages.FoundStickerSets.foundStickerSetsNotModified - } - - } -} -public extension Api.messages { - enum HighScores: TypeConstructorDescription { - case highScores(scores: [Api.HighScore], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .highScores(let scores, let users): - if boxed { - buffer.appendInt32(-1707344487) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(scores.count)) - for item in scores { - 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 .highScores(let scores, let users): - return ("highScores", [("scores", String(describing: scores)), ("users", String(describing: users))]) - } - } - - public static func parse_highScores(_ reader: BufferReader) -> HighScores? { - var _1: [Api.HighScore]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.HighScore.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.HighScores.highScores(scores: _1!, users: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum HistoryImport: TypeConstructorDescription { - case historyImport(id: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .historyImport(let id): - if boxed { - buffer.appendInt32(375566091) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .historyImport(let id): - return ("historyImport", [("id", String(describing: id))]) - } - } - - public static func parse_historyImport(_ reader: BufferReader) -> HistoryImport? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.messages.HistoryImport.historyImport(id: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum HistoryImportParsed: TypeConstructorDescription { - case historyImportParsed(flags: Int32, title: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .historyImportParsed(let flags, let title): - if boxed { - buffer.appendInt32(1578088377) + buffer.appendInt32(-1942390465) } serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .historyImportParsed(let flags, let title): - return ("historyImportParsed", [("flags", String(describing: flags)), ("title", String(describing: title))]) - } - } - - public static func parse_historyImportParsed(_ reader: BufferReader) -> HistoryImportParsed? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil - if _c1 && _c2 { - return Api.messages.HistoryImportParsed.historyImportParsed(flags: _1!, title: _2) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum InactiveChats: TypeConstructorDescription { - case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inactiveChats(let dates, let chats, let users): - if boxed { - buffer.appendInt32(-1456996667) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dates.count)) - for item in dates { - serializeInt32(item, buffer: buffer, boxed: false) - } + serializeInt32(expires, buffer: buffer, boxed: false) + peer.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) for item in chats { @@ -841,126 +318,35 @@ public extension Api.messages { for item in users { item.serialize(buffer, true) } + if Int(flags) & Int(1 << 1) != 0 {serializeString(psaType!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(psaMessage!, buffer: buffer, boxed: false)} break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inactiveChats(let dates, let chats, let users): - return ("inactiveChats", [("dates", String(describing: dates)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum MessageEditData: TypeConstructorDescription { - case messageEditData(flags: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageEditData(let flags): + case .promoDataEmpty(let expires): if boxed { - buffer.appendInt32(649453030) + buffer.appendInt32(-1728664459) } - serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(expires, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .messageEditData(let flags): - return ("messageEditData", [("flags", String(describing: flags))]) + case .promoData(let flags, let expires, let peer, let chats, let users, let psaType, let psaMessage): + return ("promoData", [("flags", String(describing: flags)), ("expires", String(describing: expires)), ("peer", String(describing: peer)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("psaType", String(describing: psaType)), ("psaMessage", String(describing: psaMessage))]) + case .promoDataEmpty(let expires): + return ("promoDataEmpty", [("expires", String(describing: expires))]) } } - public static func parse_messageEditData(_ reader: BufferReader) -> MessageEditData? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.messages.MessageEditData.messageEditData(flags: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum MessageReactionsList: TypeConstructorDescription { - case messageReactionsList(flags: Int32, count: Int32, reactions: [Api.MessagePeerReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset): - if boxed { - buffer.appendInt32(834488621) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(reactions.count)) - for item in reactions { - item.serialize(buffer, true) - } - 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) - } - if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset): - return ("messageReactionsList", [("flags", String(describing: flags)), ("count", String(describing: count)), ("reactions", String(describing: reactions)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("nextOffset", String(describing: nextOffset))]) - } - } - - public static func parse_messageReactionsList(_ reader: BufferReader) -> MessageReactionsList? { + public static func parse_promoData(_ reader: BufferReader) -> PromoData? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: [Api.MessagePeerReaction]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessagePeerReaction.self) + var _3: Api.Peer? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer } var _4: [Api.Chat]? if let _ = reader.readInt32() { @@ -971,283 +357,29 @@ public extension Api.messages { _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } var _6: String? - if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } + if Int(_1!) & Int(1 << 1) != 0 {_6 = parseString(reader) } + var _7: String? + if Int(_1!) & Int(1 << 2) != 0 {_7 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.messages.MessageReactionsList.messageReactionsList(flags: _1!, count: _2!, reactions: _3!, chats: _4!, users: _5!, nextOffset: _6) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum MessageViews: TypeConstructorDescription { - case messageViews(views: [Api.MessageViews], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageViews(let views, let chats, let users): - if boxed { - buffer.appendInt32(-1228606141) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(views.count)) - for item in views { - item.serialize(buffer, true) - } - 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 .messageViews(let views, let chats, let users): - return ("messageViews", [("views", String(describing: views)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_messageViews(_ reader: BufferReader) -> MessageViews? { - var _1: [Api.MessageViews]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageViews.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.MessageViews.messageViews(views: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum Messages: TypeConstructorDescription { - case channelMessages(flags: Int32, pts: Int32, count: Int32, offsetIdOffset: Int32?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - case messages(messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - case messagesNotModified(count: Int32) - case messagesSlice(flags: Int32, count: Int32, nextRate: Int32?, offsetIdOffset: Int32?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .channelMessages(let flags, let pts, let count, let offsetIdOffset, let messages, let chats, let users): - if boxed { - buffer.appendInt32(1682413576) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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 - case .messages(let messages, let chats, let users): - if boxed { - buffer.appendInt32(-1938715001) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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 - case .messagesNotModified(let count): - if boxed { - buffer.appendInt32(1951620897) - } - serializeInt32(count, buffer: buffer, boxed: false) - break - case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users): - if boxed { - buffer.appendInt32(978610270) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(nextRate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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 .channelMessages(let flags, let pts, let count, let offsetIdOffset, let messages, let chats, let users): - return ("channelMessages", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("count", String(describing: count)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .messages(let messages, let chats, let users): - return ("messages", [("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .messagesNotModified(let count): - return ("messagesNotModified", [("count", String(describing: count))]) - case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users): - return ("messagesSlice", [("flags", String(describing: flags)), ("count", String(describing: count)), ("nextRate", String(describing: nextRate)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_channelMessages(_ reader: BufferReader) -> Messages? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } - var _5: [Api.Message]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _6: [Api.Chat]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = 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 << 2) == 0) || _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.messages.Messages.channelMessages(flags: _1!, pts: _2!, count: _3!, offsetIdOffset: _4, messages: _5!, chats: _6!, users: _7!) + return Api.help.PromoData.promoData(flags: _1!, expires: _2!, peer: _3!, chats: _4!, users: _5!, psaType: _6, psaMessage: _7) } else { return nil } } - public static func parse_messages(_ reader: BufferReader) -> Messages? { - var _1: [Api.Message]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.Messages.messages(messages: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - public static func parse_messagesNotModified(_ reader: BufferReader) -> Messages? { + public static func parse_promoDataEmpty(_ reader: BufferReader) -> PromoData? { var _1: Int32? _1 = reader.readInt32() let _c1 = _1 != nil if _c1 { - return Api.messages.Messages.messagesNotModified(count: _1!) - } - else { - return nil - } - } - public static func parse_messagesSlice(_ reader: BufferReader) -> Messages? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } - var _4: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } - var _5: [Api.Message]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _6: [Api.Chat]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.messages.Messages.messagesSlice(flags: _1!, count: _2!, nextRate: _3, offsetIdOffset: _4, messages: _5!, chats: _6!, users: _7!) + return Api.help.PromoData.promoDataEmpty(expires: _1!) } else { return nil @@ -1256,96 +388,22 @@ public extension Api.messages { } } -public extension Api.messages { - enum PeerDialogs: TypeConstructorDescription { - case peerDialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User], state: Api.updates.State) +public extension Api.help { + enum RecentMeUrls: TypeConstructorDescription { + case recentMeUrls(urls: [Api.RecentMeUrl], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .peerDialogs(let dialogs, let messages, let chats, let users, let state): + case .recentMeUrls(let urls, let chats, let users): if boxed { - buffer.appendInt32(863093588) + buffer.appendInt32(235081943) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dialogs.count)) - for item in dialogs { + buffer.appendInt32(Int32(urls.count)) + for item in urls { item.serialize(buffer, true) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messages.count)) - for item in messages { - item.serialize(buffer, true) - } - 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) - } - state.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerDialogs(let dialogs, let messages, let chats, let users, let state): - return ("peerDialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("state", String(describing: state))]) - } - } - - public static func parse_peerDialogs(_ reader: BufferReader) -> PeerDialogs? { - var _1: [Api.Dialog]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) - } - var _2: [Api.Message]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _3: [Api.Chat]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _4: [Api.User]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _5: Api.updates.State? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.updates.State - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.PeerDialogs.peerDialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!, state: _5!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum PeerSettings: TypeConstructorDescription { - case peerSettings(settings: Api.PeerSettings, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerSettings(let settings, let chats, let users): - if boxed { - buffer.appendInt32(1753266509) - } - settings.serialize(buffer, true) - buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) for item in chats { item.serialize(buffer, true) @@ -1361,15 +419,15 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .peerSettings(let settings, let chats, let users): - return ("peerSettings", [("settings", String(describing: settings)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .recentMeUrls(let urls, let chats, let users): + return ("recentMeUrls", [("urls", String(describing: urls)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_peerSettings(_ reader: BufferReader) -> PeerSettings? { - var _1: Api.PeerSettings? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PeerSettings + public static func parse_recentMeUrls(_ reader: BufferReader) -> RecentMeUrls? { + var _1: [Api.RecentMeUrl]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RecentMeUrl.self) } var _2: [Api.Chat]? if let _ = reader.readInt32() { @@ -1383,7 +441,7 @@ public extension Api.messages { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.messages.PeerSettings.peerSettings(settings: _1!, chats: _2!, users: _3!) + return Api.help.RecentMeUrls.recentMeUrls(urls: _1!, chats: _2!, users: _3!) } else { return nil @@ -1392,37 +450,229 @@ public extension Api.messages { } } -public extension Api.messages { - enum RecentStickers: TypeConstructorDescription { - case recentStickers(hash: Int64, packs: [Api.StickerPack], stickers: [Api.Document], dates: [Int32]) - case recentStickersNotModified +public extension Api.help { + enum Support: TypeConstructorDescription { + case support(phoneNumber: String, user: Api.User) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .recentStickers(let hash, let packs, let stickers, let dates): + case .support(let phoneNumber, let user): if boxed { - buffer.appendInt32(-1999405994) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(packs.count)) - for item in packs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stickers.count)) - for item in stickers { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dates.count)) - for item in dates { - serializeInt32(item, buffer: buffer, boxed: false) + buffer.appendInt32(398898678) } + serializeString(phoneNumber, buffer: buffer, boxed: false) + user.serialize(buffer, true) break - case .recentStickersNotModified: + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .support(let phoneNumber, let user): + return ("support", [("phoneNumber", String(describing: phoneNumber)), ("user", String(describing: user))]) + } + } + + public static func parse_support(_ reader: BufferReader) -> Support? { + var _1: String? + _1 = parseString(reader) + var _2: Api.User? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.User + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.help.Support.support(phoneNumber: _1!, user: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.help { + enum SupportName: TypeConstructorDescription { + case supportName(name: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .supportName(let name): if boxed { - buffer.appendInt32(186120336) + buffer.appendInt32(-1945767479) + } + serializeString(name, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .supportName(let name): + return ("supportName", [("name", String(describing: name))]) + } + } + + public static func parse_supportName(_ reader: BufferReader) -> SupportName? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.help.SupportName.supportName(name: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.help { + enum TermsOfService: TypeConstructorDescription { + case termsOfService(flags: Int32, id: Api.DataJSON, text: String, entities: [Api.MessageEntity], minAgeConfirm: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .termsOfService(let flags, let id, let text, let entities, let minAgeConfirm): + if boxed { + buffer.appendInt32(2013922064) + } + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + serializeString(text, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(minAgeConfirm!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .termsOfService(let flags, let id, let text, let entities, let minAgeConfirm): + return ("termsOfService", [("flags", String(describing: flags)), ("id", String(describing: id)), ("text", String(describing: text)), ("entities", String(describing: entities)), ("minAgeConfirm", String(describing: minAgeConfirm))]) + } + } + + public static func parse_termsOfService(_ reader: BufferReader) -> TermsOfService? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.DataJSON? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + var _3: String? + _3 = parseString(reader) + var _4: [Api.MessageEntity]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } + var _5: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.help.TermsOfService.termsOfService(flags: _1!, id: _2!, text: _3!, entities: _4!, minAgeConfirm: _5) + } + else { + return nil + } + } + + } +} +public extension Api.help { + enum TermsOfServiceUpdate: TypeConstructorDescription { + case termsOfServiceUpdate(expires: Int32, termsOfService: Api.help.TermsOfService) + case termsOfServiceUpdateEmpty(expires: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .termsOfServiceUpdate(let expires, let termsOfService): + if boxed { + buffer.appendInt32(686618977) + } + serializeInt32(expires, buffer: buffer, boxed: false) + termsOfService.serialize(buffer, true) + break + case .termsOfServiceUpdateEmpty(let expires): + if boxed { + buffer.appendInt32(-483352705) + } + serializeInt32(expires, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .termsOfServiceUpdate(let expires, let termsOfService): + return ("termsOfServiceUpdate", [("expires", String(describing: expires)), ("termsOfService", String(describing: termsOfService))]) + case .termsOfServiceUpdateEmpty(let expires): + return ("termsOfServiceUpdateEmpty", [("expires", String(describing: expires))]) + } + } + + public static func parse_termsOfServiceUpdate(_ reader: BufferReader) -> TermsOfServiceUpdate? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.help.TermsOfService? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.help.TermsOfService + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.help.TermsOfServiceUpdate.termsOfServiceUpdate(expires: _1!, termsOfService: _2!) + } + else { + return nil + } + } + public static func parse_termsOfServiceUpdateEmpty(_ reader: BufferReader) -> TermsOfServiceUpdate? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.help.TermsOfServiceUpdate.termsOfServiceUpdateEmpty(expires: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.help { + enum UserInfo: TypeConstructorDescription { + case userInfo(message: String, entities: [Api.MessageEntity], author: String, date: Int32) + case userInfoEmpty + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .userInfo(let message, let entities, let author, let date): + if boxed { + buffer.appendInt32(32192344) + } + serializeString(message, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + serializeString(author, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + break + case .userInfoEmpty: + if boxed { + buffer.appendInt32(-206688531) } break @@ -1431,24 +681,77 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .recentStickers(let hash, let packs, let stickers, let dates): - return ("recentStickers", [("hash", String(describing: hash)), ("packs", String(describing: packs)), ("stickers", String(describing: stickers)), ("dates", String(describing: dates))]) - case .recentStickersNotModified: - return ("recentStickersNotModified", []) + case .userInfo(let message, let entities, let author, let date): + return ("userInfo", [("message", String(describing: message)), ("entities", String(describing: entities)), ("author", String(describing: author)), ("date", String(describing: date))]) + case .userInfoEmpty: + return ("userInfoEmpty", []) } } - public static func parse_recentStickers(_ reader: BufferReader) -> RecentStickers? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.StickerPack]? + public static func parse_userInfo(_ reader: BufferReader) -> UserInfo? { + var _1: String? + _1 = parseString(reader) + var _2: [Api.MessageEntity]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) } - var _3: [Api.Document]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + var _3: String? + _3 = parseString(reader) + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.help.UserInfo.userInfo(message: _1!, entities: _2!, author: _3!, date: _4!) } + else { + return nil + } + } + public static func parse_userInfoEmpty(_ reader: BufferReader) -> UserInfo? { + return Api.help.UserInfo.userInfoEmpty + } + + } +} +public extension Api.messages { + enum AffectedFoundMessages: TypeConstructorDescription { + case affectedFoundMessages(pts: Int32, ptsCount: Int32, offset: Int32, messages: [Int32]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .affectedFoundMessages(let pts, let ptsCount, let offset, let messages): + if boxed { + buffer.appendInt32(-275956116) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + serializeInt32(offset, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .affectedFoundMessages(let pts, let ptsCount, let offset, let messages): + return ("affectedFoundMessages", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("offset", String(describing: offset)), ("messages", String(describing: messages))]) + } + } + + public static func parse_affectedFoundMessages(_ reader: BufferReader) -> AffectedFoundMessages? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() var _4: [Int32]? if let _ = reader.readInt32() { _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) @@ -1458,39 +761,120 @@ public extension Api.messages { let _c3 = _3 != nil let _c4 = _4 != nil if _c1 && _c2 && _c3 && _c4 { - return Api.messages.RecentStickers.recentStickers(hash: _1!, packs: _2!, stickers: _3!, dates: _4!) + return Api.messages.AffectedFoundMessages.affectedFoundMessages(pts: _1!, ptsCount: _2!, offset: _3!, messages: _4!) } else { return nil } } - public static func parse_recentStickersNotModified(_ reader: BufferReader) -> RecentStickers? { - return Api.messages.RecentStickers.recentStickersNotModified + + } +} +public extension Api.messages { + enum AffectedHistory: TypeConstructorDescription { + case affectedHistory(pts: Int32, ptsCount: Int32, offset: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .affectedHistory(let pts, let ptsCount, let offset): + if boxed { + buffer.appendInt32(-1269012015) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + serializeInt32(offset, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .affectedHistory(let pts, let ptsCount, let offset): + return ("affectedHistory", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount)), ("offset", String(describing: offset))]) + } + } + + public static func parse_affectedHistory(_ reader: BufferReader) -> AffectedHistory? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.AffectedHistory.affectedHistory(pts: _1!, ptsCount: _2!, offset: _3!) + } + else { + return nil + } } } } public extension Api.messages { - enum SavedGifs: TypeConstructorDescription { - case savedGifs(hash: Int64, gifs: [Api.Document]) - case savedGifsNotModified + enum AffectedMessages: TypeConstructorDescription { + case affectedMessages(pts: Int32, ptsCount: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .savedGifs(let hash, let gifs): + case .affectedMessages(let pts, let ptsCount): if boxed { - buffer.appendInt32(-2069878259) + buffer.appendInt32(-2066640507) + } + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .affectedMessages(let pts, let ptsCount): + return ("affectedMessages", [("pts", String(describing: pts)), ("ptsCount", String(describing: ptsCount))]) + } + } + + public static func parse_affectedMessages(_ reader: BufferReader) -> AffectedMessages? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.AffectedMessages.affectedMessages(pts: _1!, ptsCount: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum AllStickers: TypeConstructorDescription { + case allStickers(hash: Int64, sets: [Api.StickerSet]) + case allStickersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .allStickers(let hash, let sets): + if boxed { + buffer.appendInt32(-843329861) } serializeInt64(hash, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(gifs.count)) - for item in gifs { + buffer.appendInt32(Int32(sets.count)) + for item in sets { item.serialize(buffer, true) } break - case .savedGifsNotModified: + case .allStickersNotModified: if boxed { - buffer.appendInt32(-402498398) + buffer.appendInt32(-395967805) } break @@ -1499,31 +883,495 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .savedGifs(let hash, let gifs): - return ("savedGifs", [("hash", String(describing: hash)), ("gifs", String(describing: gifs))]) - case .savedGifsNotModified: - return ("savedGifsNotModified", []) + case .allStickers(let hash, let sets): + return ("allStickers", [("hash", String(describing: hash)), ("sets", String(describing: sets))]) + case .allStickersNotModified: + return ("allStickersNotModified", []) } } - public static func parse_savedGifs(_ reader: BufferReader) -> SavedGifs? { + public static func parse_allStickers(_ reader: BufferReader) -> AllStickers? { var _1: Int64? _1 = reader.readInt64() - var _2: [Api.Document]? + var _2: [Api.StickerSet]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSet.self) } let _c1 = _1 != nil let _c2 = _2 != nil if _c1 && _c2 { - return Api.messages.SavedGifs.savedGifs(hash: _1!, gifs: _2!) + return Api.messages.AllStickers.allStickers(hash: _1!, sets: _2!) } else { return nil } } - public static func parse_savedGifsNotModified(_ reader: BufferReader) -> SavedGifs? { - return Api.messages.SavedGifs.savedGifsNotModified + public static func parse_allStickersNotModified(_ reader: BufferReader) -> AllStickers? { + return Api.messages.AllStickers.allStickersNotModified + } + + } +} +public extension Api.messages { + enum ArchivedStickers: TypeConstructorDescription { + case archivedStickers(count: Int32, sets: [Api.StickerSetCovered]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .archivedStickers(let count, let sets): + if boxed { + buffer.appendInt32(1338747336) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sets.count)) + for item in sets { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .archivedStickers(let count, let sets): + return ("archivedStickers", [("count", String(describing: count)), ("sets", String(describing: sets))]) + } + } + + public static func parse_archivedStickers(_ reader: BufferReader) -> ArchivedStickers? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.StickerSetCovered]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.ArchivedStickers.archivedStickers(count: _1!, sets: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum AvailableReactions: TypeConstructorDescription { + case availableReactions(hash: Int32, reactions: [Api.AvailableReaction]) + case availableReactionsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .availableReactions(let hash, let reactions): + if boxed { + buffer.appendInt32(1989032621) + } + serializeInt32(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(reactions.count)) + for item in reactions { + item.serialize(buffer, true) + } + break + case .availableReactionsNotModified: + if boxed { + buffer.appendInt32(-1626924713) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .availableReactions(let hash, let reactions): + return ("availableReactions", [("hash", String(describing: hash)), ("reactions", String(describing: reactions))]) + case .availableReactionsNotModified: + return ("availableReactionsNotModified", []) + } + } + + public static func parse_availableReactions(_ reader: BufferReader) -> AvailableReactions? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.AvailableReaction]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AvailableReaction.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.AvailableReactions.availableReactions(hash: _1!, reactions: _2!) + } + else { + return nil + } + } + public static func parse_availableReactionsNotModified(_ reader: BufferReader) -> AvailableReactions? { + return Api.messages.AvailableReactions.availableReactionsNotModified + } + + } +} +public extension Api.messages { + enum BotCallbackAnswer: TypeConstructorDescription { + case botCallbackAnswer(flags: Int32, message: String?, url: String?, cacheTime: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .botCallbackAnswer(let flags, let message, let url, let cacheTime): + if boxed { + buffer.appendInt32(911761060) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(message!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + serializeInt32(cacheTime, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .botCallbackAnswer(let flags, let message, let url, let cacheTime): + return ("botCallbackAnswer", [("flags", String(describing: flags)), ("message", String(describing: message)), ("url", String(describing: url)), ("cacheTime", String(describing: cacheTime))]) + } + } + + public static func parse_botCallbackAnswer(_ reader: BufferReader) -> BotCallbackAnswer? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: String? + if Int(_1!) & Int(1 << 2) != 0 {_3 = parseString(reader) } + var _4: Int32? + _4 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.messages.BotCallbackAnswer.botCallbackAnswer(flags: _1!, message: _2, url: _3, cacheTime: _4!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum BotResults: TypeConstructorDescription { + case botResults(flags: Int32, queryId: Int64, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?, results: [Api.BotInlineResult], cacheTime: Int32, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime, let users): + if boxed { + buffer.appendInt32(-1803769784) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {switchPm!.serialize(buffer, true)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(results.count)) + for item in results { + item.serialize(buffer, true) + } + serializeInt32(cacheTime, 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 .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime, let users): + return ("botResults", [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("nextOffset", String(describing: nextOffset)), ("switchPm", String(describing: switchPm)), ("results", String(describing: results)), ("cacheTime", String(describing: cacheTime)), ("users", String(describing: users))]) + } + } + + public static func parse_botResults(_ reader: BufferReader) -> BotResults? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } + var _4: Api.InlineBotSwitchPM? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.InlineBotSwitchPM + } } + var _5: [Api.BotInlineResult]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInlineResult.self) + } + var _6: Int32? + _6 = reader.readInt32() + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.messages.BotResults.botResults(flags: _1!, queryId: _2!, nextOffset: _3, switchPm: _4, results: _5!, cacheTime: _6!, users: _7!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum ChatAdminsWithInvites: TypeConstructorDescription { + case chatAdminsWithInvites(admins: [Api.ChatAdminWithInvites], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .chatAdminsWithInvites(let admins, let users): + if boxed { + buffer.appendInt32(-1231326505) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(admins.count)) + for item in admins { + 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 .chatAdminsWithInvites(let admins, let users): + return ("chatAdminsWithInvites", [("admins", String(describing: admins)), ("users", String(describing: users))]) + } + } + + public static func parse_chatAdminsWithInvites(_ reader: BufferReader) -> ChatAdminsWithInvites? { + var _1: [Api.ChatAdminWithInvites]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChatAdminWithInvites.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.ChatAdminsWithInvites.chatAdminsWithInvites(admins: _1!, users: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum ChatFull: TypeConstructorDescription { + case chatFull(fullChat: Api.ChatFull, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .chatFull(let fullChat, let chats, let users): + if boxed { + buffer.appendInt32(-438840932) + } + fullChat.serialize(buffer, true) + 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 .chatFull(let fullChat, let chats, let users): + return ("chatFull", [("fullChat", String(describing: fullChat)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_chatFull(_ reader: BufferReader) -> ChatFull? { + var _1: Api.ChatFull? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.ChatFull + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.ChatFull.chatFull(fullChat: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum ChatInviteImporters: TypeConstructorDescription { + case chatInviteImporters(count: Int32, importers: [Api.ChatInviteImporter], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .chatInviteImporters(let count, let importers, let users): + if boxed { + buffer.appendInt32(-2118733814) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(importers.count)) + for item in importers { + 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 .chatInviteImporters(let count, let importers, let users): + return ("chatInviteImporters", [("count", String(describing: count)), ("importers", String(describing: importers)), ("users", String(describing: users))]) + } + } + + public static func parse_chatInviteImporters(_ reader: BufferReader) -> ChatInviteImporters? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.ChatInviteImporter]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChatInviteImporter.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.ChatInviteImporters.chatInviteImporters(count: _1!, importers: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum Chats: TypeConstructorDescription { + case chats(chats: [Api.Chat]) + case chatsSlice(count: Int32, chats: [Api.Chat]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .chats(let chats): + if boxed { + buffer.appendInt32(1694474197) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + break + case .chatsSlice(let count, let chats): + if boxed { + buffer.appendInt32(-1663561404) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .chats(let chats): + return ("chats", [("chats", String(describing: chats))]) + case .chatsSlice(let count, let chats): + return ("chatsSlice", [("count", String(describing: count)), ("chats", String(describing: chats))]) + } + } + + public static func parse_chats(_ reader: BufferReader) -> Chats? { + var _1: [Api.Chat]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.messages.Chats.chats(chats: _1!) + } + else { + return nil + } + } + public static func parse_chatsSlice(_ reader: BufferReader) -> Chats? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.Chats.chatsSlice(count: _1!, chats: _2!) + } + else { + return nil + } } } diff --git a/submodules/TelegramApi/Sources/Api25.swift b/submodules/TelegramApi/Sources/Api25.swift index 9dadf48c72..8d01ba6f9e 100644 --- a/submodules/TelegramApi/Sources/Api25.swift +++ b/submodules/TelegramApi/Sources/Api25.swift @@ -1,41 +1,31 @@ public extension Api.messages { - enum SearchCounter: TypeConstructorDescription { - case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32) + enum CheckedHistoryImportPeer: TypeConstructorDescription { + case checkedHistoryImportPeer(confirmText: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .searchCounter(let flags, let filter, let count): + case .checkedHistoryImportPeer(let confirmText): if boxed { - buffer.appendInt32(-398136321) + buffer.appendInt32(-1571952873) } - serializeInt32(flags, buffer: buffer, boxed: false) - filter.serialize(buffer, true) - serializeInt32(count, buffer: buffer, boxed: false) + serializeString(confirmText, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .searchCounter(let flags, let filter, let count): - return ("searchCounter", [("flags", String(describing: flags)), ("filter", String(describing: filter)), ("count", String(describing: count))]) + case .checkedHistoryImportPeer(let confirmText): + return ("checkedHistoryImportPeer", [("confirmText", String(describing: confirmText))]) } } - public static func parse_searchCounter(_ reader: BufferReader) -> SearchCounter? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.MessagesFilter? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.MessagesFilter - } - var _3: Int32? - _3 = reader.readInt32() + public static func parse_checkedHistoryImportPeer(_ reader: BufferReader) -> CheckedHistoryImportPeer? { + var _1: String? + _1 = parseString(reader) let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.SearchCounter.searchCounter(flags: _1!, filter: _2!, count: _3!) + if _c1 { + return Api.messages.CheckedHistoryImportPeer.checkedHistoryImportPeer(confirmText: _1!) } else { return nil @@ -45,23 +35,120 @@ public extension Api.messages { } } public extension Api.messages { - enum SearchResultsCalendar: TypeConstructorDescription { - case searchResultsCalendar(flags: Int32, count: Int32, minDate: Int32, minMsgId: Int32, offsetIdOffset: Int32?, periods: [Api.SearchResultsCalendarPeriod], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + enum DhConfig: TypeConstructorDescription { + case dhConfig(g: Int32, p: Buffer, version: Int32, random: Buffer) + case dhConfigNotModified(random: Buffer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users): + case .dhConfig(let g, let p, let version, let random): if boxed { - buffer.appendInt32(343859772) + buffer.appendInt32(740433629) + } + serializeInt32(g, buffer: buffer, boxed: false) + serializeBytes(p, buffer: buffer, boxed: false) + serializeInt32(version, buffer: buffer, boxed: false) + serializeBytes(random, buffer: buffer, boxed: false) + break + case .dhConfigNotModified(let random): + if boxed { + buffer.appendInt32(-1058912715) + } + serializeBytes(random, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .dhConfig(let g, let p, let version, let random): + return ("dhConfig", [("g", String(describing: g)), ("p", String(describing: p)), ("version", String(describing: version)), ("random", String(describing: random))]) + case .dhConfigNotModified(let random): + return ("dhConfigNotModified", [("random", String(describing: random))]) + } + } + + public static func parse_dhConfig(_ reader: BufferReader) -> DhConfig? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Int32? + _3 = reader.readInt32() + var _4: Buffer? + _4 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.messages.DhConfig.dhConfig(g: _1!, p: _2!, version: _3!, random: _4!) + } + else { + return nil + } + } + public static func parse_dhConfigNotModified(_ reader: BufferReader) -> DhConfig? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.messages.DhConfig.dhConfigNotModified(random: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum Dialogs: TypeConstructorDescription { + case dialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + case dialogsNotModified(count: Int32) + case dialogsSlice(count: Int32, dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .dialogs(let dialogs, let messages, let chats, let users): + if boxed { + buffer.appendInt32(364538944) } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - serializeInt32(minDate, buffer: buffer, boxed: false) - serializeInt32(minMsgId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} buffer.appendInt32(481674261) - buffer.appendInt32(Int32(periods.count)) - for item in periods { + buffer.appendInt32(Int32(dialogs.count)) + for item in dialogs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + 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 + case .dialogsNotModified(let count): + if boxed { + buffer.appendInt32(-253500010) + } + serializeInt32(count, buffer: buffer, boxed: false) + break + case .dialogsSlice(let count, let dialogs, let messages, let chats, let users): + if boxed { + buffer.appendInt32(1910543603) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dialogs.count)) + for item in dialogs { item.serialize(buffer, true) } buffer.appendInt32(481674261) @@ -85,157 +172,80 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users): - return ("searchResultsCalendar", [("flags", String(describing: flags)), ("count", String(describing: count)), ("minDate", String(describing: minDate)), ("minMsgId", String(describing: minMsgId)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("periods", String(describing: periods)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .dialogs(let dialogs, let messages, let chats, let users): + return ("dialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .dialogsNotModified(let count): + return ("dialogsNotModified", [("count", String(describing: count))]) + case .dialogsSlice(let count, let dialogs, let messages, let chats, let users): + return ("dialogsSlice", [("count", String(describing: count)), ("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_searchResultsCalendar(_ reader: BufferReader) -> SearchResultsCalendar? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } - var _6: [Api.SearchResultsCalendarPeriod]? + public static func parse_dialogs(_ reader: BufferReader) -> Dialogs? { + var _1: [Api.Dialog]? if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsCalendarPeriod.self) + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) } - var _7: [Api.Message]? + var _2: [Api.Message]? if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) } - var _8: [Api.Chat]? + var _3: [Api.Chat]? if let _ = reader.readInt32() { - _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) } - var _9: [Api.User]? + var _4: [Api.User]? if let _ = reader.readInt32() { - _9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.messages.SearchResultsCalendar.searchResultsCalendar(flags: _1!, count: _2!, minDate: _3!, minMsgId: _4!, offsetIdOffset: _5, periods: _6!, messages: _7!, chats: _8!, users: _9!) + if _c1 && _c2 && _c3 && _c4 { + return Api.messages.Dialogs.dialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!) } else { return nil } } - - } -} -public extension Api.messages { - enum SearchResultsPositions: TypeConstructorDescription { - case searchResultsPositions(count: Int32, positions: [Api.SearchResultsPosition]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .searchResultsPositions(let count, let positions): - if boxed { - buffer.appendInt32(1404185519) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(positions.count)) - for item in positions { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .searchResultsPositions(let count, let positions): - return ("searchResultsPositions", [("count", String(describing: count)), ("positions", String(describing: positions))]) - } - } - - public static func parse_searchResultsPositions(_ reader: BufferReader) -> SearchResultsPositions? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.SearchResultsPosition]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsPosition.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.SearchResultsPositions.searchResultsPositions(count: _1!, positions: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum SentEncryptedMessage: TypeConstructorDescription { - case sentEncryptedFile(date: Int32, file: Api.EncryptedFile) - case sentEncryptedMessage(date: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sentEncryptedFile(let date, let file): - if boxed { - buffer.appendInt32(-1802240206) - } - serializeInt32(date, buffer: buffer, boxed: false) - file.serialize(buffer, true) - break - case .sentEncryptedMessage(let date): - if boxed { - buffer.appendInt32(1443858741) - } - serializeInt32(date, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .sentEncryptedFile(let date, let file): - return ("sentEncryptedFile", [("date", String(describing: date)), ("file", String(describing: file))]) - case .sentEncryptedMessage(let date): - return ("sentEncryptedMessage", [("date", String(describing: date))]) - } - } - - public static func parse_sentEncryptedFile(_ reader: BufferReader) -> SentEncryptedMessage? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.EncryptedFile? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.EncryptedFile - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.SentEncryptedMessage.sentEncryptedFile(date: _1!, file: _2!) - } - else { - return nil - } - } - public static func parse_sentEncryptedMessage(_ reader: BufferReader) -> SentEncryptedMessage? { + public static func parse_dialogsNotModified(_ reader: BufferReader) -> Dialogs? { var _1: Int32? _1 = reader.readInt32() let _c1 = _1 != nil if _c1 { - return Api.messages.SentEncryptedMessage.sentEncryptedMessage(date: _1!) + return Api.messages.Dialogs.dialogsNotModified(count: _1!) + } + else { + return nil + } + } + public static func parse_dialogsSlice(_ reader: BufferReader) -> Dialogs? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Dialog]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) + } + var _3: [Api.Message]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _4: [Api.Chat]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + 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 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.Dialogs.dialogsSlice(count: _1!, dialogs: _2!, messages: _3!, chats: _4!, users: _5!) } else { return nil @@ -245,20 +255,582 @@ public extension Api.messages { } } public extension Api.messages { - enum SponsoredMessages: TypeConstructorDescription { - case sponsoredMessages(messages: [Api.SponsoredMessage], chats: [Api.Chat], users: [Api.User]) + enum DiscussionMessage: TypeConstructorDescription { + case discussionMessage(flags: Int32, messages: [Api.Message], maxId: Int32?, readInboxMaxId: Int32?, readOutboxMaxId: Int32?, unreadCount: Int32, chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .sponsoredMessages(let messages, let chats, let users): + case .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users): if boxed { - buffer.appendInt32(1705297877) + buffer.appendInt32(-1506535550) } + serializeInt32(flags, buffer: buffer, boxed: false) buffer.appendInt32(481674261) buffer.appendInt32(Int32(messages.count)) for item in messages { item.serialize(buffer, true) } + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(maxId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(readInboxMaxId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(readOutboxMaxId!, buffer: buffer, boxed: false)} + serializeInt32(unreadCount, 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 .discussionMessage(let flags, let messages, let maxId, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chats, let users): + return ("discussionMessage", [("flags", String(describing: flags)), ("messages", String(describing: messages)), ("maxId", String(describing: maxId)), ("readInboxMaxId", String(describing: readInboxMaxId)), ("readOutboxMaxId", String(describing: readOutboxMaxId)), ("unreadCount", String(describing: unreadCount)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_discussionMessage(_ reader: BufferReader) -> DiscussionMessage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Message]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() } + var _5: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_5 = reader.readInt32() } + var _6: Int32? + _6 = reader.readInt32() + var _7: [Api.Chat]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _8: [Api.User]? + if let _ = reader.readInt32() { + _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 { + return Api.messages.DiscussionMessage.discussionMessage(flags: _1!, messages: _2!, maxId: _3, readInboxMaxId: _4, readOutboxMaxId: _5, unreadCount: _6!, chats: _7!, users: _8!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum ExportedChatInvite: TypeConstructorDescription { + case exportedChatInvite(invite: Api.ExportedChatInvite, users: [Api.User]) + case exportedChatInviteReplaced(invite: Api.ExportedChatInvite, newInvite: Api.ExportedChatInvite, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .exportedChatInvite(let invite, let users): + if boxed { + buffer.appendInt32(410107472) + } + invite.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + case .exportedChatInviteReplaced(let invite, let newInvite, let users): + if boxed { + buffer.appendInt32(572915951) + } + invite.serialize(buffer, true) + newInvite.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 .exportedChatInvite(let invite, let users): + return ("exportedChatInvite", [("invite", String(describing: invite)), ("users", String(describing: users))]) + case .exportedChatInviteReplaced(let invite, let newInvite, let users): + return ("exportedChatInviteReplaced", [("invite", String(describing: invite)), ("newInvite", String(describing: newInvite)), ("users", String(describing: users))]) + } + } + + public static func parse_exportedChatInvite(_ reader: BufferReader) -> ExportedChatInvite? { + var _1: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.ExportedChatInvite.exportedChatInvite(invite: _1!, users: _2!) + } + else { + return nil + } + } + public static func parse_exportedChatInviteReplaced(_ reader: BufferReader) -> ExportedChatInvite? { + var _1: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } + var _2: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.ExportedChatInvite.exportedChatInviteReplaced(invite: _1!, newInvite: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum ExportedChatInvites: TypeConstructorDescription { + case exportedChatInvites(count: Int32, invites: [Api.ExportedChatInvite], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .exportedChatInvites(let count, let invites, let users): + if boxed { + buffer.appendInt32(-1111085620) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(invites.count)) + for item in invites { + 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 .exportedChatInvites(let count, let invites, let users): + return ("exportedChatInvites", [("count", String(describing: count)), ("invites", String(describing: invites)), ("users", String(describing: users))]) + } + } + + public static func parse_exportedChatInvites(_ reader: BufferReader) -> ExportedChatInvites? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.ExportedChatInvite]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ExportedChatInvite.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.ExportedChatInvites.exportedChatInvites(count: _1!, invites: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum FavedStickers: TypeConstructorDescription { + case favedStickers(hash: Int64, packs: [Api.StickerPack], stickers: [Api.Document]) + case favedStickersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .favedStickers(let hash, let packs, let stickers): + if boxed { + buffer.appendInt32(750063767) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(packs.count)) + for item in packs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stickers.count)) + for item in stickers { + item.serialize(buffer, true) + } + break + case .favedStickersNotModified: + if boxed { + buffer.appendInt32(-1634752813) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .favedStickers(let hash, let packs, let stickers): + return ("favedStickers", [("hash", String(describing: hash)), ("packs", String(describing: packs)), ("stickers", String(describing: stickers))]) + case .favedStickersNotModified: + return ("favedStickersNotModified", []) + } + } + + public static func parse_favedStickers(_ reader: BufferReader) -> FavedStickers? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.StickerPack]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + } + var _3: [Api.Document]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.FavedStickers.favedStickers(hash: _1!, packs: _2!, stickers: _3!) + } + else { + return nil + } + } + public static func parse_favedStickersNotModified(_ reader: BufferReader) -> FavedStickers? { + return Api.messages.FavedStickers.favedStickersNotModified + } + + } +} +public extension Api.messages { + enum FeaturedStickers: TypeConstructorDescription { + case featuredStickers(flags: Int32, hash: Int64, count: Int32, sets: [Api.StickerSetCovered], unread: [Int64]) + case featuredStickersNotModified(count: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .featuredStickers(let flags, let hash, let count, let sets, let unread): + if boxed { + buffer.appendInt32(-1103615738) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sets.count)) + for item in sets { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(unread.count)) + for item in unread { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .featuredStickersNotModified(let count): + if boxed { + buffer.appendInt32(-958657434) + } + serializeInt32(count, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .featuredStickers(let flags, let hash, let count, let sets, let unread): + return ("featuredStickers", [("flags", String(describing: flags)), ("hash", String(describing: hash)), ("count", String(describing: count)), ("sets", String(describing: sets)), ("unread", String(describing: unread))]) + case .featuredStickersNotModified(let count): + return ("featuredStickersNotModified", [("count", String(describing: count))]) + } + } + + public static func parse_featuredStickers(_ reader: BufferReader) -> FeaturedStickers? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + var _4: [Api.StickerSetCovered]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + } + var _5: [Int64]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.FeaturedStickers.featuredStickers(flags: _1!, hash: _2!, count: _3!, sets: _4!, unread: _5!) + } + else { + return nil + } + } + public static func parse_featuredStickersNotModified(_ reader: BufferReader) -> FeaturedStickers? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.messages.FeaturedStickers.featuredStickersNotModified(count: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum FoundStickerSets: TypeConstructorDescription { + case foundStickerSets(hash: Int64, sets: [Api.StickerSetCovered]) + case foundStickerSetsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .foundStickerSets(let hash, let sets): + if boxed { + buffer.appendInt32(-1963942446) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sets.count)) + for item in sets { + item.serialize(buffer, true) + } + break + case .foundStickerSetsNotModified: + if boxed { + buffer.appendInt32(223655517) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .foundStickerSets(let hash, let sets): + return ("foundStickerSets", [("hash", String(describing: hash)), ("sets", String(describing: sets))]) + case .foundStickerSetsNotModified: + return ("foundStickerSetsNotModified", []) + } + } + + public static func parse_foundStickerSets(_ reader: BufferReader) -> FoundStickerSets? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.StickerSetCovered]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.FoundStickerSets.foundStickerSets(hash: _1!, sets: _2!) + } + else { + return nil + } + } + public static func parse_foundStickerSetsNotModified(_ reader: BufferReader) -> FoundStickerSets? { + return Api.messages.FoundStickerSets.foundStickerSetsNotModified + } + + } +} +public extension Api.messages { + enum HighScores: TypeConstructorDescription { + case highScores(scores: [Api.HighScore], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .highScores(let scores, let users): + if boxed { + buffer.appendInt32(-1707344487) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(scores.count)) + for item in scores { + 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 .highScores(let scores, let users): + return ("highScores", [("scores", String(describing: scores)), ("users", String(describing: users))]) + } + } + + public static func parse_highScores(_ reader: BufferReader) -> HighScores? { + var _1: [Api.HighScore]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.HighScore.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.HighScores.highScores(scores: _1!, users: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum HistoryImport: TypeConstructorDescription { + case historyImport(id: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .historyImport(let id): + if boxed { + buffer.appendInt32(375566091) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .historyImport(let id): + return ("historyImport", [("id", String(describing: id))]) + } + } + + public static func parse_historyImport(_ reader: BufferReader) -> HistoryImport? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.messages.HistoryImport.historyImport(id: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum HistoryImportParsed: TypeConstructorDescription { + case historyImportParsed(flags: Int32, title: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .historyImportParsed(let flags, let title): + if boxed { + buffer.appendInt32(1578088377) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .historyImportParsed(let flags, let title): + return ("historyImportParsed", [("flags", String(describing: flags)), ("title", String(describing: title))]) + } + } + + public static func parse_historyImportParsed(_ reader: BufferReader) -> HistoryImportParsed? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil + if _c1 && _c2 { + return Api.messages.HistoryImportParsed.historyImportParsed(flags: _1!, title: _2) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum InactiveChats: TypeConstructorDescription { + case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inactiveChats(let dates, let chats, let users): + if boxed { + buffer.appendInt32(-1456996667) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dates.count)) + for item in dates { + serializeInt32(item, buffer: buffer, boxed: false) + } buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) for item in chats { @@ -275,15 +847,15 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .sponsoredMessages(let messages, let chats, let users): - return ("sponsoredMessages", [("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .inactiveChats(let dates, let chats, let users): + return ("inactiveChats", [("dates", String(describing: dates)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_sponsoredMessages(_ reader: BufferReader) -> SponsoredMessages? { - var _1: [Api.SponsoredMessage]? + public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { + var _1: [Int32]? if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SponsoredMessage.self) + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) } var _2: [Api.Chat]? if let _ = reader.readInt32() { @@ -297,7 +869,7 @@ public extension Api.messages { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.messages.SponsoredMessages.sponsoredMessages(messages: _1!, chats: _2!, users: _3!) + return Api.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) } else { return nil @@ -307,271 +879,33 @@ public extension Api.messages { } } public extension Api.messages { - enum StickerSet: TypeConstructorDescription { - case stickerSet(set: Api.StickerSet, packs: [Api.StickerPack], documents: [Api.Document]) - case stickerSetNotModified + enum MessageEditData: TypeConstructorDescription { + case messageEditData(flags: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .stickerSet(let set, let packs, let documents): + case .messageEditData(let flags): if boxed { - buffer.appendInt32(-1240849242) - } - set.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(packs.count)) - for item in packs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(documents.count)) - for item in documents { - item.serialize(buffer, true) - } - break - case .stickerSetNotModified: - if boxed { - buffer.appendInt32(-738646805) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stickerSet(let set, let packs, let documents): - return ("stickerSet", [("set", String(describing: set)), ("packs", String(describing: packs)), ("documents", String(describing: documents))]) - case .stickerSetNotModified: - return ("stickerSetNotModified", []) - } - } - - public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { - var _1: Api.StickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StickerSet - } - var _2: [Api.StickerPack]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) - } - var _3: [Api.Document]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.StickerSet.stickerSet(set: _1!, packs: _2!, documents: _3!) - } - else { - return nil - } - } - public static func parse_stickerSetNotModified(_ reader: BufferReader) -> StickerSet? { - return Api.messages.StickerSet.stickerSetNotModified - } - - } -} -public extension Api.messages { - enum StickerSetInstallResult: TypeConstructorDescription { - case stickerSetInstallResultArchive(sets: [Api.StickerSetCovered]) - case stickerSetInstallResultSuccess - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .stickerSetInstallResultArchive(let sets): - if boxed { - buffer.appendInt32(904138920) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sets.count)) - for item in sets { - item.serialize(buffer, true) - } - break - case .stickerSetInstallResultSuccess: - if boxed { - buffer.appendInt32(946083368) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stickerSetInstallResultArchive(let sets): - return ("stickerSetInstallResultArchive", [("sets", String(describing: sets))]) - case .stickerSetInstallResultSuccess: - return ("stickerSetInstallResultSuccess", []) - } - } - - public static func parse_stickerSetInstallResultArchive(_ reader: BufferReader) -> StickerSetInstallResult? { - var _1: [Api.StickerSetCovered]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.messages.StickerSetInstallResult.stickerSetInstallResultArchive(sets: _1!) - } - else { - return nil - } - } - public static func parse_stickerSetInstallResultSuccess(_ reader: BufferReader) -> StickerSetInstallResult? { - return Api.messages.StickerSetInstallResult.stickerSetInstallResultSuccess - } - - } -} -public extension Api.messages { - enum Stickers: TypeConstructorDescription { - case stickers(hash: Int64, stickers: [Api.Document]) - case stickersNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .stickers(let hash, let stickers): - if boxed { - buffer.appendInt32(816245886) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stickers.count)) - for item in stickers { - item.serialize(buffer, true) - } - break - case .stickersNotModified: - if boxed { - buffer.appendInt32(-244016606) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stickers(let hash, let stickers): - return ("stickers", [("hash", String(describing: hash)), ("stickers", String(describing: stickers))]) - case .stickersNotModified: - return ("stickersNotModified", []) - } - } - - public static func parse_stickers(_ reader: BufferReader) -> Stickers? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.Document]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.Stickers.stickers(hash: _1!, stickers: _2!) - } - else { - return nil - } - } - public static func parse_stickersNotModified(_ reader: BufferReader) -> Stickers? { - return Api.messages.Stickers.stickersNotModified - } - - } -} -public extension Api.messages { - enum TranscribedAudio: TypeConstructorDescription { - case transcribedAudio(flags: Int32, transcriptionId: Int64, text: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .transcribedAudio(let flags, let transcriptionId, let text): - if boxed { - buffer.appendInt32(-1821037486) + buffer.appendInt32(649453030) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(transcriptionId, buffer: buffer, boxed: false) - serializeString(text, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .transcribedAudio(let flags, let transcriptionId, let text): - return ("transcribedAudio", [("flags", String(describing: flags)), ("transcriptionId", String(describing: transcriptionId)), ("text", String(describing: text))]) + case .messageEditData(let flags): + return ("messageEditData", [("flags", String(describing: flags))]) } } - public static func parse_transcribedAudio(_ reader: BufferReader) -> TranscribedAudio? { + public static func parse_messageEditData(_ reader: BufferReader) -> MessageEditData? { var _1: Int32? _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: String? - _3 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.messages.TranscribedAudio.transcribedAudio(flags: _1!, transcriptionId: _2!, text: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum TranslatedText: TypeConstructorDescription { - case translateNoResult - case translateResultText(text: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .translateNoResult: - if boxed { - buffer.appendInt32(1741309751) - } - - break - case .translateResultText(let text): - if boxed { - buffer.appendInt32(-1575684144) - } - serializeString(text, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .translateNoResult: - return ("translateNoResult", []) - case .translateResultText(let text): - return ("translateResultText", [("text", String(describing: text))]) - } - } - - public static func parse_translateNoResult(_ reader: BufferReader) -> TranslatedText? { - return Api.messages.TranslatedText.translateNoResult - } - public static func parse_translateResultText(_ reader: BufferReader) -> TranslatedText? { - var _1: String? - _1 = parseString(reader) let _c1 = _1 != nil if _c1 { - return Api.messages.TranslatedText.translateResultText(text: _1!) + return Api.messages.MessageEditData.messageEditData(flags: _1!) } else { return nil @@ -581,20 +915,25 @@ public extension Api.messages { } } public extension Api.messages { - enum VotesList: TypeConstructorDescription { - case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) + enum MessageReactionsList: TypeConstructorDescription { + case messageReactionsList(flags: Int32, count: Int32, reactions: [Api.MessagePeerReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): + case .messageReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset): if boxed { - buffer.appendInt32(136574537) + buffer.appendInt32(834488621) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(count, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(votes.count)) - for item in votes { + buffer.appendInt32(Int32(reactions.count)) + for item in reactions { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { item.serialize(buffer, true) } buffer.appendInt32(481674261) @@ -609,739 +948,38 @@ public extension Api.messages { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .votesList(let flags, let count, let votes, let users, let nextOffset): - return ("votesList", [("flags", String(describing: flags)), ("count", String(describing: count)), ("votes", String(describing: votes)), ("users", String(describing: users)), ("nextOffset", String(describing: nextOffset))]) + case .messageReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset): + return ("messageReactionsList", [("flags", String(describing: flags)), ("count", String(describing: count)), ("reactions", String(describing: reactions)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("nextOffset", String(describing: nextOffset))]) } } - public static func parse_votesList(_ reader: BufferReader) -> VotesList? { + public static func parse_messageReactionsList(_ reader: BufferReader) -> MessageReactionsList? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: [Api.MessageUserVote]? + var _3: [Api.MessagePeerReaction]? if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessagePeerReaction.self) } - var _4: [Api.User]? + var _4: [Api.Chat]? if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) } - var _5: String? - if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum BankCardData: TypeConstructorDescription { - case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .bankCardData(let title, let openUrls): - if boxed { - buffer.appendInt32(1042605427) - } - serializeString(title, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(openUrls.count)) - for item in openUrls { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .bankCardData(let title, let openUrls): - return ("bankCardData", [("title", String(describing: title)), ("openUrls", String(describing: openUrls))]) - } - } - - public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? { - var _1: String? - _1 = parseString(reader) - var _2: [Api.BankCardOpenUrl]? + var _5: [Api.User]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BankCardOpenUrl.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.payments.BankCardData.bankCardData(title: _1!, openUrls: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum ExportedInvoice: TypeConstructorDescription { - case exportedInvoice(url: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .exportedInvoice(let url): - if boxed { - buffer.appendInt32(-1362048039) - } - serializeString(url, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .exportedInvoice(let url): - return ("exportedInvoice", [("url", String(describing: url))]) - } - } - - public static func parse_exportedInvoice(_ reader: BufferReader) -> ExportedInvoice? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.payments.ExportedInvoice.exportedInvoice(url: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum PaymentForm: TypeConstructorDescription { - case paymentForm(flags: Int32, formId: Int64, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, providerId: Int64, url: String, nativeProvider: String?, nativeParams: Api.DataJSON?, savedInfo: Api.PaymentRequestedInfo?, savedCredentials: Api.PaymentSavedCredentials?, users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let savedInfo, let savedCredentials, let users): - if boxed { - buffer.appendInt32(-1340916937) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(formId, buffer: buffer, boxed: false) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(description, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} - invoice.serialize(buffer, true) - serializeInt64(providerId, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 4) != 0 {serializeString(nativeProvider!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {nativeParams!.serialize(buffer, true)} - if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {savedCredentials!.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 .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let savedInfo, let savedCredentials, let users): - return ("paymentForm", [("flags", String(describing: flags)), ("formId", String(describing: formId)), ("botId", String(describing: botId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("invoice", String(describing: invoice)), ("providerId", String(describing: providerId)), ("url", String(describing: url)), ("nativeProvider", String(describing: nativeProvider)), ("nativeParams", String(describing: nativeParams)), ("savedInfo", String(describing: savedInfo)), ("savedCredentials", String(describing: savedCredentials)), ("users", String(describing: users))]) - } - } - - public static func parse_paymentForm(_ reader: BufferReader) -> PaymentForm? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: Api.WebDocument? - if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.WebDocument - } } - var _7: Api.Invoice? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.Invoice - } - var _8: Int64? - _8 = reader.readInt64() - var _9: String? - _9 = parseString(reader) - var _10: String? - if Int(_1!) & Int(1 << 4) != 0 {_10 = parseString(reader) } - var _11: Api.DataJSON? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.DataJSON - } } - var _12: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _12 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - var _13: Api.PaymentSavedCredentials? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.PaymentSavedCredentials - } } - var _14: [Api.User]? - if let _ = reader.readInt32() { - _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 5) == 0) || _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 4) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 0) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 1) == 0) || _13 != nil - let _c14 = _14 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { - return Api.payments.PaymentForm.paymentForm(flags: _1!, formId: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, providerId: _8!, url: _9!, nativeProvider: _10, nativeParams: _11, savedInfo: _12, savedCredentials: _13, users: _14!) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum PaymentReceipt: TypeConstructorDescription { - case paymentReceipt(flags: Int32, date: Int32, botId: Int64, providerId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, info: Api.PaymentRequestedInfo?, shipping: Api.ShippingOption?, tipAmount: Int64?, currency: String, totalAmount: Int64, credentialsTitle: String, users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentReceipt(let flags, let date, let botId, let providerId, let title, let description, let photo, let invoice, let info, let shipping, let tipAmount, let currency, let totalAmount, let credentialsTitle, let users): - if boxed { - buffer.appendInt32(1891958275) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeInt64(providerId, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(description, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)} - invoice.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {shipping!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {serializeInt64(tipAmount!, buffer: buffer, boxed: false)} - serializeString(currency, buffer: buffer, boxed: false) - serializeInt64(totalAmount, buffer: buffer, boxed: false) - serializeString(credentialsTitle, 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 .paymentReceipt(let flags, let date, let botId, let providerId, let title, let description, let photo, let invoice, let info, let shipping, let tipAmount, let currency, let totalAmount, let credentialsTitle, let users): - return ("paymentReceipt", [("flags", String(describing: flags)), ("date", String(describing: date)), ("botId", String(describing: botId)), ("providerId", String(describing: providerId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("invoice", String(describing: invoice)), ("info", String(describing: info)), ("shipping", String(describing: shipping)), ("tipAmount", String(describing: tipAmount)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("credentialsTitle", String(describing: credentialsTitle)), ("users", String(describing: users))]) - } - } - - public static func parse_paymentReceipt(_ reader: BufferReader) -> PaymentReceipt? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - var _4: Int64? - _4 = reader.readInt64() - var _5: String? - _5 = parseString(reader) var _6: String? - _6 = parseString(reader) - var _7: Api.WebDocument? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.WebDocument - } } - var _8: Api.Invoice? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.Invoice - } - var _9: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - var _10: Api.ShippingOption? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.ShippingOption - } } - var _11: Int64? - if Int(_1!) & Int(1 << 3) != 0 {_11 = reader.readInt64() } - var _12: String? - _12 = parseString(reader) - var _13: Int64? - _13 = reader.readInt64() - var _14: String? - _14 = parseString(reader) - var _15: [Api.User]? - if let _ = reader.readInt32() { - _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } + if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil - let _c8 = _8 != nil - let _c9 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil - let _c10 = (Int(_1!) & Int(1 << 1) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 3) == 0) || _11 != nil - let _c12 = _12 != nil - let _c13 = _13 != nil - let _c14 = _14 != nil - let _c15 = _15 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { - return Api.payments.PaymentReceipt.paymentReceipt(flags: _1!, date: _2!, botId: _3!, providerId: _4!, title: _5!, description: _6!, photo: _7, invoice: _8!, info: _9, shipping: _10, tipAmount: _11, currency: _12!, totalAmount: _13!, credentialsTitle: _14!, users: _15!) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum PaymentResult: TypeConstructorDescription { - case paymentResult(updates: Api.Updates) - case paymentVerificationNeeded(url: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentResult(let updates): - if boxed { - buffer.appendInt32(1314881805) - } - updates.serialize(buffer, true) - break - case .paymentVerificationNeeded(let url): - if boxed { - buffer.appendInt32(-666824391) - } - serializeString(url, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .paymentResult(let updates): - return ("paymentResult", [("updates", String(describing: updates))]) - case .paymentVerificationNeeded(let url): - return ("paymentVerificationNeeded", [("url", String(describing: url))]) - } - } - - public static func parse_paymentResult(_ reader: BufferReader) -> PaymentResult? { - var _1: Api.Updates? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Updates - } - let _c1 = _1 != nil - if _c1 { - return Api.payments.PaymentResult.paymentResult(updates: _1!) - } - else { - return nil - } - } - public static func parse_paymentVerificationNeeded(_ reader: BufferReader) -> PaymentResult? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.payments.PaymentResult.paymentVerificationNeeded(url: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum SavedInfo: TypeConstructorDescription { - case savedInfo(flags: Int32, savedInfo: Api.PaymentRequestedInfo?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .savedInfo(let flags, let savedInfo): - if boxed { - buffer.appendInt32(-74456004) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .savedInfo(let flags, let savedInfo): - return ("savedInfo", [("flags", String(describing: flags)), ("savedInfo", String(describing: savedInfo))]) - } - } - - public static func parse_savedInfo(_ reader: BufferReader) -> SavedInfo? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - if _c1 && _c2 { - return Api.payments.SavedInfo.savedInfo(flags: _1!, savedInfo: _2) - } - else { - return nil - } - } - - } -} -public extension Api.payments { - enum ValidatedRequestedInfo: TypeConstructorDescription { - case validatedRequestedInfo(flags: Int32, id: String?, shippingOptions: [Api.ShippingOption]?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .validatedRequestedInfo(let flags, let id, let shippingOptions): - if boxed { - buffer.appendInt32(-784000893) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(id!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(shippingOptions!.count)) - for item in shippingOptions! { - item.serialize(buffer, true) - }} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .validatedRequestedInfo(let flags, let id, let shippingOptions): - return ("validatedRequestedInfo", [("flags", String(describing: flags)), ("id", String(describing: id)), ("shippingOptions", String(describing: shippingOptions))]) - } - } - - public static func parse_validatedRequestedInfo(_ reader: BufferReader) -> ValidatedRequestedInfo? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } - var _3: [Api.ShippingOption]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ShippingOption.self) - } } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.payments.ValidatedRequestedInfo.validatedRequestedInfo(flags: _1!, id: _2, shippingOptions: _3) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum ExportedGroupCallInvite: TypeConstructorDescription { - case exportedGroupCallInvite(link: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .exportedGroupCallInvite(let link): - if boxed { - buffer.appendInt32(541839704) - } - serializeString(link, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .exportedGroupCallInvite(let link): - return ("exportedGroupCallInvite", [("link", String(describing: link))]) - } - } - - public static func parse_exportedGroupCallInvite(_ reader: BufferReader) -> ExportedGroupCallInvite? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.phone.ExportedGroupCallInvite.exportedGroupCallInvite(link: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum GroupCall: TypeConstructorDescription { - case groupCall(call: Api.GroupCall, participants: [Api.GroupCallParticipant], participantsNextOffset: String, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .groupCall(let call, let participants, let participantsNextOffset, let chats, let users): - if boxed { - buffer.appendInt32(-1636664659) - } - call.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(participants.count)) - for item in participants { - item.serialize(buffer, true) - } - serializeString(participantsNextOffset, 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 .groupCall(let call, let participants, let participantsNextOffset, let chats, let users): - return ("groupCall", [("call", String(describing: call)), ("participants", String(describing: participants)), ("participantsNextOffset", String(describing: participantsNextOffset)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - } - } - - public static func parse_groupCall(_ reader: BufferReader) -> GroupCall? { - var _1: Api.GroupCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.GroupCall - } - var _2: [Api.GroupCallParticipant]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) - } - var _3: String? - _3 = parseString(reader) - var _4: [Api.Chat]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - 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 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.phone.GroupCall.groupCall(call: _1!, participants: _2!, participantsNextOffset: _3!, chats: _4!, users: _5!) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum GroupCallStreamChannels: TypeConstructorDescription { - case groupCallStreamChannels(channels: [Api.GroupCallStreamChannel]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .groupCallStreamChannels(let channels): - if boxed { - buffer.appendInt32(-790330702) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(channels.count)) - for item in channels { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .groupCallStreamChannels(let channels): - return ("groupCallStreamChannels", [("channels", String(describing: channels))]) - } - } - - public static func parse_groupCallStreamChannels(_ reader: BufferReader) -> GroupCallStreamChannels? { - var _1: [Api.GroupCallStreamChannel]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallStreamChannel.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.phone.GroupCallStreamChannels.groupCallStreamChannels(channels: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum GroupCallStreamRtmpUrl: TypeConstructorDescription { - case groupCallStreamRtmpUrl(url: String, key: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .groupCallStreamRtmpUrl(let url, let key): - if boxed { - buffer.appendInt32(767505458) - } - serializeString(url, buffer: buffer, boxed: false) - serializeString(key, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .groupCallStreamRtmpUrl(let url, let key): - return ("groupCallStreamRtmpUrl", [("url", String(describing: url)), ("key", String(describing: key))]) - } - } - - public static func parse_groupCallStreamRtmpUrl(_ reader: BufferReader) -> GroupCallStreamRtmpUrl? { - var _1: String? - _1 = parseString(reader) - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.phone.GroupCallStreamRtmpUrl.groupCallStreamRtmpUrl(url: _1!, key: _2!) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum GroupParticipants: TypeConstructorDescription { - case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], nextOffset: String, chats: [Api.Chat], users: [Api.User], version: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version): - if boxed { - buffer.appendInt32(-193506890) - } - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(participants.count)) - for item in participants { - item.serialize(buffer, true) - } - 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) - } - serializeInt32(version, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version): - return ("groupParticipants", [("count", String(describing: count)), ("participants", String(describing: participants)), ("nextOffset", String(describing: nextOffset)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("version", String(describing: version))]) - } - } - - public static func parse_groupParticipants(_ reader: BufferReader) -> GroupParticipants? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.GroupCallParticipant]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) - } - var _3: String? - _3 = parseString(reader) - var _4: [Api.Chat]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _5: [Api.User]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _6: Int32? - _6 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, nextOffset: _3!, chats: _4!, users: _5!, version: _6!) + return Api.messages.MessageReactionsList.messageReactionsList(flags: _1!, count: _2!, reactions: _3!, chats: _4!, users: _5!, nextOffset: _6) } else { return nil @@ -1350,19 +988,19 @@ public extension Api.phone { } } -public extension Api.phone { - enum JoinAsPeers: TypeConstructorDescription { - case joinAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) +public extension Api.messages { + enum MessageViews: TypeConstructorDescription { + case messageViews(views: [Api.MessageViews], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .joinAsPeers(let peers, let chats, let users): + case .messageViews(let views, let chats, let users): if boxed { - buffer.appendInt32(-1343921601) + buffer.appendInt32(-1228606141) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { + buffer.appendInt32(Int32(views.count)) + for item in views { item.serialize(buffer, true) } buffer.appendInt32(481674261) @@ -1381,15 +1019,15 @@ public extension Api.phone { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .joinAsPeers(let peers, let chats, let users): - return ("joinAsPeers", [("peers", String(describing: peers)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .messageViews(let views, let chats, let users): + return ("messageViews", [("views", String(describing: views)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_joinAsPeers(_ reader: BufferReader) -> JoinAsPeers? { - var _1: [Api.Peer]? + public static func parse_messageViews(_ reader: BufferReader) -> MessageViews? { + var _1: [Api.MessageViews]? if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageViews.self) } var _2: [Api.Chat]? if let _ = reader.readInt32() { @@ -1403,7 +1041,7 @@ public extension Api.phone { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.phone.JoinAsPeers.joinAsPeers(peers: _1!, chats: _2!, users: _3!) + return Api.messages.MessageViews.messageViews(views: _1!, chats: _2!, users: _3!) } else { return nil @@ -1412,17 +1050,83 @@ public extension Api.phone { } } -public extension Api.phone { - enum PhoneCall: TypeConstructorDescription { - case phoneCall(phoneCall: Api.PhoneCall, users: [Api.User]) +public extension Api.messages { + enum Messages: TypeConstructorDescription { + case channelMessages(flags: Int32, pts: Int32, count: Int32, offsetIdOffset: Int32?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + case messages(messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + case messagesNotModified(count: Int32) + case messagesSlice(flags: Int32, count: Int32, nextRate: Int32?, offsetIdOffset: Int32?, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .phoneCall(let phoneCall, let users): + case .channelMessages(let flags, let pts, let count, let offsetIdOffset, let messages, let chats, let users): if boxed { - buffer.appendInt32(-326966976) + buffer.appendInt32(1682413576) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + 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 + case .messages(let messages, let chats, let users): + if boxed { + buffer.appendInt32(-1938715001) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + 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 + case .messagesNotModified(let count): + if boxed { + buffer.appendInt32(1951620897) + } + serializeInt32(count, buffer: buffer, boxed: false) + break + case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users): + if boxed { + buffer.appendInt32(978610270) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(nextRate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) } - phoneCall.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { @@ -1434,24 +1138,116 @@ public extension Api.phone { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .phoneCall(let phoneCall, let users): - return ("phoneCall", [("phoneCall", String(describing: phoneCall)), ("users", String(describing: users))]) + case .channelMessages(let flags, let pts, let count, let offsetIdOffset, let messages, let chats, let users): + return ("channelMessages", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("count", String(describing: count)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .messages(let messages, let chats, let users): + return ("messages", [("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .messagesNotModified(let count): + return ("messagesNotModified", [("count", String(describing: count))]) + case .messagesSlice(let flags, let count, let nextRate, let offsetIdOffset, let messages, let chats, let users): + return ("messagesSlice", [("flags", String(describing: flags)), ("count", String(describing: count)), ("nextRate", String(describing: nextRate)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { - var _1: Api.PhoneCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall - } - var _2: [Api.User]? + public static func parse_channelMessages(_ reader: BufferReader) -> Messages? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } + var _5: [Api.Message]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _6: [Api.Chat]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.phone.PhoneCall.phoneCall(phoneCall: _1!, users: _2!) + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.messages.Messages.channelMessages(flags: _1!, pts: _2!, count: _3!, offsetIdOffset: _4, messages: _5!, chats: _6!, users: _7!) + } + else { + return nil + } + } + public static func parse_messages(_ reader: BufferReader) -> Messages? { + var _1: [Api.Message]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.Messages.messages(messages: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + public static func parse_messagesNotModified(_ reader: BufferReader) -> Messages? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.messages.Messages.messagesNotModified(count: _1!) + } + else { + return nil + } + } + public static func parse_messagesSlice(_ reader: BufferReader) -> Messages? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() } + var _4: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() } + var _5: [Api.Message]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _6: [Api.Chat]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.messages.Messages.messagesSlice(flags: _1!, count: _2!, nextRate: _3, offsetIdOffset: _4, messages: _5!, chats: _6!, users: _7!) } else { return nil @@ -1460,17 +1256,100 @@ public extension Api.phone { } } -public extension Api.photos { - enum Photo: TypeConstructorDescription { - case photo(photo: Api.Photo, users: [Api.User]) +public extension Api.messages { + enum PeerDialogs: TypeConstructorDescription { + case peerDialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User], state: Api.updates.State) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .photo(let photo, let users): + case .peerDialogs(let dialogs, let messages, let chats, let users, let state): if boxed { - buffer.appendInt32(539045032) + buffer.appendInt32(863093588) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dialogs.count)) + for item in dialogs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + 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) + } + state.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerDialogs(let dialogs, let messages, let chats, let users, let state): + return ("peerDialogs", [("dialogs", String(describing: dialogs)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("state", String(describing: state))]) + } + } + + public static func parse_peerDialogs(_ reader: BufferReader) -> PeerDialogs? { + var _1: [Api.Dialog]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Dialog.self) + } + var _2: [Api.Message]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _3: [Api.Chat]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _5: Api.updates.State? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.updates.State + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.PeerDialogs.peerDialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!, state: _5!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum PeerSettings: TypeConstructorDescription { + case peerSettings(settings: Api.PeerSettings, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerSettings(let settings, let chats, let users): + if boxed { + buffer.appendInt32(1753266509) + } + settings.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) } - photo.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { @@ -1482,24 +1361,29 @@ public extension Api.photos { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .photo(let photo, let users): - return ("photo", [("photo", String(describing: photo)), ("users", String(describing: users))]) + case .peerSettings(let settings, let chats, let users): + return ("peerSettings", [("settings", String(describing: settings)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_photo(_ reader: BufferReader) -> Photo? { - var _1: Api.Photo? + public static func parse_peerSettings(_ reader: BufferReader) -> PeerSettings? { + var _1: Api.PeerSettings? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Photo + _1 = Api.parse(reader, signature: signature) as? Api.PeerSettings } - var _2: [Api.User]? + var _2: [Api.Chat]? if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil - if _c1 && _c2 { - return Api.photos.Photo.photo(photo: _1!, users: _2!) + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.PeerSettings.peerSettings(settings: _1!, chats: _2!, users: _3!) } else { return nil @@ -1508,3 +1392,139 @@ public extension Api.photos { } } +public extension Api.messages { + enum RecentStickers: TypeConstructorDescription { + case recentStickers(hash: Int64, packs: [Api.StickerPack], stickers: [Api.Document], dates: [Int32]) + case recentStickersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .recentStickers(let hash, let packs, let stickers, let dates): + if boxed { + buffer.appendInt32(-1999405994) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(packs.count)) + for item in packs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stickers.count)) + for item in stickers { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dates.count)) + for item in dates { + serializeInt32(item, buffer: buffer, boxed: false) + } + break + case .recentStickersNotModified: + if boxed { + buffer.appendInt32(186120336) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .recentStickers(let hash, let packs, let stickers, let dates): + return ("recentStickers", [("hash", String(describing: hash)), ("packs", String(describing: packs)), ("stickers", String(describing: stickers)), ("dates", String(describing: dates))]) + case .recentStickersNotModified: + return ("recentStickersNotModified", []) + } + } + + public static func parse_recentStickers(_ reader: BufferReader) -> RecentStickers? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.StickerPack]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + } + var _3: [Api.Document]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + var _4: [Int32]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.messages.RecentStickers.recentStickers(hash: _1!, packs: _2!, stickers: _3!, dates: _4!) + } + else { + return nil + } + } + public static func parse_recentStickersNotModified(_ reader: BufferReader) -> RecentStickers? { + return Api.messages.RecentStickers.recentStickersNotModified + } + + } +} +public extension Api.messages { + enum SavedGifs: TypeConstructorDescription { + case savedGifs(hash: Int64, gifs: [Api.Document]) + case savedGifsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .savedGifs(let hash, let gifs): + if boxed { + buffer.appendInt32(-2069878259) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(gifs.count)) + for item in gifs { + item.serialize(buffer, true) + } + break + case .savedGifsNotModified: + if boxed { + buffer.appendInt32(-402498398) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .savedGifs(let hash, let gifs): + return ("savedGifs", [("hash", String(describing: hash)), ("gifs", String(describing: gifs))]) + case .savedGifsNotModified: + return ("savedGifsNotModified", []) + } + } + + public static func parse_savedGifs(_ reader: BufferReader) -> SavedGifs? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.Document]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.SavedGifs.savedGifs(hash: _1!, gifs: _2!) + } + else { + return nil + } + } + public static func parse_savedGifsNotModified(_ reader: BufferReader) -> SavedGifs? { + return Api.messages.SavedGifs.savedGifsNotModified + } + + } +} diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index 58fa0773fb..1845664eae 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -1,87 +1,41 @@ -public extension Api.photos { - enum Photos: TypeConstructorDescription { - case photos(photos: [Api.Photo], users: [Api.User]) - case photosSlice(count: Int32, photos: [Api.Photo], users: [Api.User]) +public extension Api.messages { + enum SearchCounter: TypeConstructorDescription { + case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .photos(let photos, let users): + case .searchCounter(let flags, let filter, let count): if boxed { - buffer.appendInt32(-1916114267) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(photos.count)) - for item in photos { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - case .photosSlice(let count, let photos, let users): - if boxed { - buffer.appendInt32(352657236) + buffer.appendInt32(-398136321) } + serializeInt32(flags, buffer: buffer, boxed: false) + filter.serialize(buffer, true) serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(photos.count)) - for item in photos { - 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 .photos(let photos, let users): - return ("photos", [("photos", String(describing: photos)), ("users", String(describing: users))]) - case .photosSlice(let count, let photos, let users): - return ("photosSlice", [("count", String(describing: count)), ("photos", String(describing: photos)), ("users", String(describing: users))]) + case .searchCounter(let flags, let filter, let count): + return ("searchCounter", [("flags", String(describing: flags)), ("filter", String(describing: filter)), ("count", String(describing: count))]) } } - public static func parse_photos(_ reader: BufferReader) -> Photos? { - var _1: [Api.Photo]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.photos.Photos.photos(photos: _1!, users: _2!) - } - else { - return nil - } - } - public static func parse_photosSlice(_ reader: BufferReader) -> Photos? { + public static func parse_searchCounter(_ reader: BufferReader) -> SearchCounter? { var _1: Int32? _1 = reader.readInt32() - var _2: [Api.Photo]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) - } - var _3: [Api.User]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + var _2: Api.MessagesFilter? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.MessagesFilter } + var _3: Int32? + _3 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.photos.Photos.photosSlice(count: _1!, photos: _2!, users: _3!) + return Api.messages.SearchCounter.searchCounter(flags: _1!, filter: _2!, count: _3!) } else { return nil @@ -90,544 +44,27 @@ public extension Api.photos { } } -public extension Api.stats { - enum BroadcastStats: TypeConstructorDescription { - case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, recentMessageInteractions: [Api.MessageInteractionCounters]) +public extension Api.messages { + enum SearchResultsCalendar: TypeConstructorDescription { + case searchResultsCalendar(flags: Int32, count: Int32, minDate: Int32, minMsgId: Int32, offsetIdOffset: Int32?, periods: [Api.SearchResultsCalendarPeriod], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions): + case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users): if boxed { - buffer.appendInt32(-1107852396) - } - period.serialize(buffer, true) - followers.serialize(buffer, true) - viewsPerPost.serialize(buffer, true) - sharesPerPost.serialize(buffer, true) - enabledNotifications.serialize(buffer, true) - growthGraph.serialize(buffer, true) - followersGraph.serialize(buffer, true) - muteGraph.serialize(buffer, true) - topHoursGraph.serialize(buffer, true) - interactionsGraph.serialize(buffer, true) - ivInteractionsGraph.serialize(buffer, true) - viewsBySourceGraph.serialize(buffer, true) - newFollowersBySourceGraph.serialize(buffer, true) - languagesGraph.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(recentMessageInteractions.count)) - for item in recentMessageInteractions { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions): - return ("broadcastStats", [("period", String(describing: period)), ("followers", String(describing: followers)), ("viewsPerPost", String(describing: viewsPerPost)), ("sharesPerPost", String(describing: sharesPerPost)), ("enabledNotifications", String(describing: enabledNotifications)), ("growthGraph", String(describing: growthGraph)), ("followersGraph", String(describing: followersGraph)), ("muteGraph", String(describing: muteGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("interactionsGraph", String(describing: interactionsGraph)), ("ivInteractionsGraph", String(describing: ivInteractionsGraph)), ("viewsBySourceGraph", String(describing: viewsBySourceGraph)), ("newFollowersBySourceGraph", String(describing: newFollowersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("recentMessageInteractions", String(describing: recentMessageInteractions))]) - } - } - - public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? { - var _1: Api.StatsDateRangeDays? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays - } - var _2: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _3: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _4: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _5: Api.StatsPercentValue? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue - } - var _6: Api.StatsGraph? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _7: Api.StatsGraph? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _8: Api.StatsGraph? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _9: Api.StatsGraph? - if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _10: Api.StatsGraph? - if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _11: Api.StatsGraph? - if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _12: Api.StatsGraph? - if let signature = reader.readInt32() { - _12 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _13: Api.StatsGraph? - if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _14: Api.StatsGraph? - if let signature = reader.readInt32() { - _14 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _15: [Api.MessageInteractionCounters]? - if let _ = reader.readInt32() { - _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageInteractionCounters.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = _10 != nil - let _c11 = _11 != nil - let _c12 = _12 != nil - let _c13 = _13 != nil - let _c14 = _14 != nil - let _c15 = _15 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { - return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, growthGraph: _6!, followersGraph: _7!, muteGraph: _8!, topHoursGraph: _9!, interactionsGraph: _10!, ivInteractionsGraph: _11!, viewsBySourceGraph: _12!, newFollowersBySourceGraph: _13!, languagesGraph: _14!, recentMessageInteractions: _15!) - } - else { - return nil - } - } - - } -} -public extension Api.stats { - enum MegagroupStats: TypeConstructorDescription { - case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users): - if boxed { - buffer.appendInt32(-276825834) - } - period.serialize(buffer, true) - members.serialize(buffer, true) - messages.serialize(buffer, true) - viewers.serialize(buffer, true) - posters.serialize(buffer, true) - growthGraph.serialize(buffer, true) - membersGraph.serialize(buffer, true) - newMembersBySourceGraph.serialize(buffer, true) - languagesGraph.serialize(buffer, true) - messagesGraph.serialize(buffer, true) - actionsGraph.serialize(buffer, true) - topHoursGraph.serialize(buffer, true) - weekdaysGraph.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(topPosters.count)) - for item in topPosters { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(topAdmins.count)) - for item in topAdmins { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(topInviters.count)) - for item in topInviters { - 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 .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users): - return ("megagroupStats", [("period", String(describing: period)), ("members", String(describing: members)), ("messages", String(describing: messages)), ("viewers", String(describing: viewers)), ("posters", String(describing: posters)), ("growthGraph", String(describing: growthGraph)), ("membersGraph", String(describing: membersGraph)), ("newMembersBySourceGraph", String(describing: newMembersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("messagesGraph", String(describing: messagesGraph)), ("actionsGraph", String(describing: actionsGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("weekdaysGraph", String(describing: weekdaysGraph)), ("topPosters", String(describing: topPosters)), ("topAdmins", String(describing: topAdmins)), ("topInviters", String(describing: topInviters)), ("users", String(describing: users))]) - } - } - - public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? { - var _1: Api.StatsDateRangeDays? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays - } - var _2: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _3: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _4: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _5: Api.StatsAbsValueAndPrev? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev - } - var _6: Api.StatsGraph? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _7: Api.StatsGraph? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _8: Api.StatsGraph? - if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _9: Api.StatsGraph? - if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _10: Api.StatsGraph? - if let signature = reader.readInt32() { - _10 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _11: Api.StatsGraph? - if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _12: Api.StatsGraph? - if let signature = reader.readInt32() { - _12 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _13: Api.StatsGraph? - if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - var _14: [Api.StatsGroupTopPoster]? - if let _ = reader.readInt32() { - _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self) - } - var _15: [Api.StatsGroupTopAdmin]? - if let _ = reader.readInt32() { - _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self) - } - var _16: [Api.StatsGroupTopInviter]? - if let _ = reader.readInt32() { - _16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self) - } - var _17: [Api.User]? - if let _ = reader.readInt32() { - _17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = _10 != nil - let _c11 = _11 != nil - let _c12 = _12 != nil - let _c13 = _13 != nil - let _c14 = _14 != nil - let _c15 = _15 != nil - let _c16 = _16 != nil - let _c17 = _17 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 { - return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!) - } - else { - return nil - } - } - - } -} -public extension Api.stats { - enum MessageStats: TypeConstructorDescription { - case messageStats(viewsGraph: Api.StatsGraph) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .messageStats(let viewsGraph): - if boxed { - buffer.appendInt32(-1986399595) - } - viewsGraph.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .messageStats(let viewsGraph): - return ("messageStats", [("viewsGraph", String(describing: viewsGraph))]) - } - } - - public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? { - var _1: Api.StatsGraph? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - let _c1 = _1 != nil - if _c1 { - return Api.stats.MessageStats.messageStats(viewsGraph: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.stickers { - enum SuggestedShortName: TypeConstructorDescription { - case suggestedShortName(shortName: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .suggestedShortName(let shortName): - if boxed { - buffer.appendInt32(-2046910401) - } - serializeString(shortName, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .suggestedShortName(let shortName): - return ("suggestedShortName", [("shortName", String(describing: shortName))]) - } - } - - public static func parse_suggestedShortName(_ reader: BufferReader) -> SuggestedShortName? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.stickers.SuggestedShortName.suggestedShortName(shortName: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.storage { - enum FileType: TypeConstructorDescription { - case fileGif - case fileJpeg - case fileMov - case fileMp3 - case fileMp4 - case filePartial - case filePdf - case filePng - case fileUnknown - case fileWebp - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .fileGif: - if boxed { - buffer.appendInt32(-891180321) - } - - break - case .fileJpeg: - if boxed { - buffer.appendInt32(8322574) - } - - break - case .fileMov: - if boxed { - buffer.appendInt32(1258941372) - } - - break - case .fileMp3: - if boxed { - buffer.appendInt32(1384777335) - } - - break - case .fileMp4: - if boxed { - buffer.appendInt32(-1278304028) - } - - break - case .filePartial: - if boxed { - buffer.appendInt32(1086091090) - } - - break - case .filePdf: - if boxed { - buffer.appendInt32(-1373745011) - } - - break - case .filePng: - if boxed { - buffer.appendInt32(172975040) - } - - break - case .fileUnknown: - if boxed { - buffer.appendInt32(-1432995067) - } - - break - case .fileWebp: - if boxed { - buffer.appendInt32(276907596) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .fileGif: - return ("fileGif", []) - case .fileJpeg: - return ("fileJpeg", []) - case .fileMov: - return ("fileMov", []) - case .fileMp3: - return ("fileMp3", []) - case .fileMp4: - return ("fileMp4", []) - case .filePartial: - return ("filePartial", []) - case .filePdf: - return ("filePdf", []) - case .filePng: - return ("filePng", []) - case .fileUnknown: - return ("fileUnknown", []) - case .fileWebp: - return ("fileWebp", []) - } - } - - public static func parse_fileGif(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileGif - } - public static func parse_fileJpeg(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileJpeg - } - public static func parse_fileMov(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileMov - } - public static func parse_fileMp3(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileMp3 - } - public static func parse_fileMp4(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileMp4 - } - public static func parse_filePartial(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.filePartial - } - public static func parse_filePdf(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.filePdf - } - public static func parse_filePng(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.filePng - } - public static func parse_fileUnknown(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileUnknown - } - public static func parse_fileWebp(_ reader: BufferReader) -> FileType? { - return Api.storage.FileType.fileWebp - } - - } -} -public extension Api.updates { - enum ChannelDifference: TypeConstructorDescription { - case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User]) - case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?) - case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): - if boxed { - buffer.appendInt32(543450958) + buffer.appendInt32(343859772) } serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + serializeInt32(count, buffer: buffer, boxed: false) + serializeInt32(minDate, buffer: buffer, boxed: false) + serializeInt32(minMsgId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(offsetIdOffset!, buffer: buffer, boxed: false)} buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newMessages.count)) - for item in newMessages { + buffer.appendInt32(Int32(periods.count)) + for item in periods { item.serialize(buffer, true) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUpdates.count)) - for item in otherUpdates { - item.serialize(buffer, true) - } - 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 - case .channelDifferenceEmpty(let flags, let pts, let timeout): - if boxed { - buffer.appendInt32(1041346555) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} - break - case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): - if boxed { - buffer.appendInt32(-1531132162) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} - dialog.serialize(buffer, true) - buffer.appendInt32(481674261) buffer.appendInt32(Int32(messages.count)) for item in messages { item.serialize(buffer, true) @@ -648,337 +85,12 @@ public extension Api.updates { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): - return ("channelDifference", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("timeout", String(describing: timeout)), ("newMessages", String(describing: newMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users))]) - case .channelDifferenceEmpty(let flags, let pts, let timeout): - return ("channelDifferenceEmpty", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("timeout", String(describing: timeout))]) - case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): - return ("channelDifferenceTooLong", [("flags", String(describing: flags)), ("timeout", String(describing: timeout)), ("dialog", String(describing: dialog)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .searchResultsCalendar(let flags, let count, let minDate, let minMsgId, let offsetIdOffset, let periods, let messages, let chats, let users): + return ("searchResultsCalendar", [("flags", String(describing: flags)), ("count", String(describing: count)), ("minDate", String(describing: minDate)), ("minMsgId", String(describing: minMsgId)), ("offsetIdOffset", String(describing: offsetIdOffset)), ("periods", String(describing: periods)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - var _4: [Api.Message]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _5: [Api.Update]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _6: [Api.Chat]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _7: [Api.User]? - if let _ = reader.readInt32() { - _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!) - } - else { - return nil - } - } - public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil - if _c1 && _c2 && _c3 { - return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3) - } - else { - return nil - } - } - public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } - var _3: Api.Dialog? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Dialog - } - var _4: [Api.Message]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - 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 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!) - } - else { - return nil - } - } - - } -} -public extension Api.updates { - enum Difference: TypeConstructorDescription { - case difference(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], state: Api.updates.State) - case differenceEmpty(date: Int32, seq: Int32) - case differenceSlice(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], intermediateState: Api.updates.State) - case differenceTooLong(pts: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .difference(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let state): - if boxed { - buffer.appendInt32(16030880) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newMessages.count)) - for item in newMessages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newEncryptedMessages.count)) - for item in newEncryptedMessages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUpdates.count)) - for item in otherUpdates { - item.serialize(buffer, true) - } - 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) - } - state.serialize(buffer, true) - break - case .differenceEmpty(let date, let seq): - if boxed { - buffer.appendInt32(1567990072) - } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(seq, buffer: buffer, boxed: false) - break - case .differenceSlice(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let intermediateState): - if boxed { - buffer.appendInt32(-1459938943) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newMessages.count)) - for item in newMessages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(newEncryptedMessages.count)) - for item in newEncryptedMessages { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUpdates.count)) - for item in otherUpdates { - item.serialize(buffer, true) - } - 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) - } - intermediateState.serialize(buffer, true) - break - case .differenceTooLong(let pts): - if boxed { - buffer.appendInt32(1258196845) - } - serializeInt32(pts, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .difference(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let state): - return ("difference", [("newMessages", String(describing: newMessages)), ("newEncryptedMessages", String(describing: newEncryptedMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("state", String(describing: state))]) - case .differenceEmpty(let date, let seq): - return ("differenceEmpty", [("date", String(describing: date)), ("seq", String(describing: seq))]) - case .differenceSlice(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let intermediateState): - return ("differenceSlice", [("newMessages", String(describing: newMessages)), ("newEncryptedMessages", String(describing: newEncryptedMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("intermediateState", String(describing: intermediateState))]) - case .differenceTooLong(let pts): - return ("differenceTooLong", [("pts", String(describing: pts))]) - } - } - - public static func parse_difference(_ reader: BufferReader) -> Difference? { - var _1: [Api.Message]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _2: [Api.EncryptedMessage]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.EncryptedMessage.self) - } - var _3: [Api.Update]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _4: [Api.Chat]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _5: [Api.User]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _6: Api.updates.State? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.updates.State - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.updates.Difference.difference(newMessages: _1!, newEncryptedMessages: _2!, otherUpdates: _3!, chats: _4!, users: _5!, state: _6!) - } - else { - return nil - } - } - public static func parse_differenceEmpty(_ reader: BufferReader) -> Difference? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.updates.Difference.differenceEmpty(date: _1!, seq: _2!) - } - else { - return nil - } - } - public static func parse_differenceSlice(_ reader: BufferReader) -> Difference? { - var _1: [Api.Message]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) - } - var _2: [Api.EncryptedMessage]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.EncryptedMessage.self) - } - var _3: [Api.Update]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) - } - var _4: [Api.Chat]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _5: [Api.User]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - var _6: Api.updates.State? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.updates.State - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.updates.Difference.differenceSlice(newMessages: _1!, newEncryptedMessages: _2!, otherUpdates: _3!, chats: _4!, users: _5!, intermediateState: _6!) - } - else { - return nil - } - } - public static func parse_differenceTooLong(_ reader: BufferReader) -> Difference? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.updates.Difference.differenceTooLong(pts: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.updates { - enum State: TypeConstructorDescription { - case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .state(let pts, let qts, let date, let seq, let unreadCount): - if boxed { - buffer.appendInt32(-1519637954) - } - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(qts, buffer: buffer, boxed: false) - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(seq, buffer: buffer, boxed: false) - serializeInt32(unreadCount, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .state(let pts, let qts, let date, let seq, let unreadCount): - return ("state", [("pts", String(describing: pts)), ("qts", String(describing: qts)), ("date", String(describing: date)), ("seq", String(describing: seq)), ("unreadCount", String(describing: unreadCount))]) - } - } - - public static func parse_state(_ reader: BufferReader) -> State? { + public static func parse_searchResultsCalendar(_ reader: BufferReader) -> SearchResultsCalendar? { var _1: Int32? _1 = reader.readInt32() var _2: Int32? @@ -988,14 +100,34 @@ public extension Api.updates { var _4: Int32? _4 = reader.readInt32() var _5: Int32? - _5 = reader.readInt32() + if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() } + var _6: [Api.SearchResultsCalendarPeriod]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsCalendarPeriod.self) + } + var _7: [Api.Message]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _8: [Api.Chat]? + if let _ = reader.readInt32() { + _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _9: [Api.User]? + if let _ = reader.readInt32() { + _9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!) + let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { + return Api.messages.SearchResultsCalendar.searchResultsCalendar(flags: _1!, count: _2!, minDate: _3!, minMsgId: _4!, offsetIdOffset: _5, periods: _6!, messages: _7!, chats: _8!, users: _9!) } else { return nil @@ -1004,88 +136,20 @@ public extension Api.updates { } } -public extension Api.upload { - enum CdnFile: TypeConstructorDescription { - case cdnFile(bytes: Buffer) - case cdnFileReuploadNeeded(requestToken: Buffer) +public extension Api.messages { + enum SearchResultsPositions: TypeConstructorDescription { + case searchResultsPositions(count: Int32, positions: [Api.SearchResultsPosition]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .cdnFile(let bytes): + case .searchResultsPositions(let count, let positions): if boxed { - buffer.appendInt32(-1449145777) + buffer.appendInt32(1404185519) } - serializeBytes(bytes, buffer: buffer, boxed: false) - break - case .cdnFileReuploadNeeded(let requestToken): - if boxed { - buffer.appendInt32(-290921362) - } - serializeBytes(requestToken, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .cdnFile(let bytes): - return ("cdnFile", [("bytes", String(describing: bytes))]) - case .cdnFileReuploadNeeded(let requestToken): - return ("cdnFileReuploadNeeded", [("requestToken", String(describing: requestToken))]) - } - } - - public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.upload.CdnFile.cdnFile(bytes: _1!) - } - else { - return nil - } - } - public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!) - } - else { - return nil - } - } - - } -} -public extension Api.upload { - enum File: TypeConstructorDescription { - case file(type: Api.storage.FileType, mtime: Int32, bytes: Buffer) - case fileCdnRedirect(dcId: Int32, fileToken: Buffer, encryptionKey: Buffer, encryptionIv: Buffer, fileHashes: [Api.FileHash]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .file(let type, let mtime, let bytes): - if boxed { - buffer.appendInt32(157948117) - } - type.serialize(buffer, true) - serializeInt32(mtime, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) - break - case .fileCdnRedirect(let dcId, let fileToken, let encryptionKey, let encryptionIv, let fileHashes): - if boxed { - buffer.appendInt32(-242427324) - } - serializeInt32(dcId, buffer: buffer, boxed: false) - serializeBytes(fileToken, buffer: buffer, boxed: false) - serializeBytes(encryptionKey, buffer: buffer, boxed: false) - serializeBytes(encryptionIv, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(fileHashes.count)) - for item in fileHashes { + buffer.appendInt32(Int32(positions.count)) + for item in positions { item.serialize(buffer, true) } break @@ -1094,52 +158,22 @@ public extension Api.upload { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .file(let type, let mtime, let bytes): - return ("file", [("type", String(describing: type)), ("mtime", String(describing: mtime)), ("bytes", String(describing: bytes))]) - case .fileCdnRedirect(let dcId, let fileToken, let encryptionKey, let encryptionIv, let fileHashes): - return ("fileCdnRedirect", [("dcId", String(describing: dcId)), ("fileToken", String(describing: fileToken)), ("encryptionKey", String(describing: encryptionKey)), ("encryptionIv", String(describing: encryptionIv)), ("fileHashes", String(describing: fileHashes))]) + case .searchResultsPositions(let count, let positions): + return ("searchResultsPositions", [("count", String(describing: count)), ("positions", String(describing: positions))]) } } - public static func parse_file(_ reader: BufferReader) -> File? { - var _1: Api.storage.FileType? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.storage.FileType - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Buffer? - _3 = parseBytes(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.upload.File.file(type: _1!, mtime: _2!, bytes: _3!) - } - else { - return nil - } - } - public static func parse_fileCdnRedirect(_ reader: BufferReader) -> File? { + public static func parse_searchResultsPositions(_ reader: BufferReader) -> SearchResultsPositions? { var _1: Int32? _1 = reader.readInt32() - var _2: Buffer? - _2 = parseBytes(reader) - var _3: Buffer? - _3 = parseBytes(reader) - var _4: Buffer? - _4 = parseBytes(reader) - var _5: [Api.FileHash]? + var _2: [Api.SearchResultsPosition]? if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SearchResultsPosition.self) } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.upload.File.fileCdnRedirect(dcId: _1!, fileToken: _2!, encryptionKey: _3!, encryptionIv: _4!, fileHashes: _5!) + if _c1 && _c2 { + return Api.messages.SearchResultsPositions.searchResultsPositions(count: _1!, positions: _2!) } else { return nil @@ -1148,52 +182,60 @@ public extension Api.upload { } } -public extension Api.upload { - enum WebFile: TypeConstructorDescription { - case webFile(size: Int32, mimeType: String, fileType: Api.storage.FileType, mtime: Int32, bytes: Buffer) +public extension Api.messages { + enum SentEncryptedMessage: TypeConstructorDescription { + case sentEncryptedFile(date: Int32, file: Api.EncryptedFile) + case sentEncryptedMessage(date: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .webFile(let size, let mimeType, let fileType, let mtime, let bytes): + case .sentEncryptedFile(let date, let file): if boxed { - buffer.appendInt32(568808380) + buffer.appendInt32(-1802240206) } - serializeInt32(size, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - fileType.serialize(buffer, true) - serializeInt32(mtime, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + file.serialize(buffer, true) + break + case .sentEncryptedMessage(let date): + if boxed { + buffer.appendInt32(1443858741) + } + serializeInt32(date, buffer: buffer, boxed: false) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .webFile(let size, let mimeType, let fileType, let mtime, let bytes): - return ("webFile", [("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("fileType", String(describing: fileType)), ("mtime", String(describing: mtime)), ("bytes", String(describing: bytes))]) + case .sentEncryptedFile(let date, let file): + return ("sentEncryptedFile", [("date", String(describing: date)), ("file", String(describing: file))]) + case .sentEncryptedMessage(let date): + return ("sentEncryptedMessage", [("date", String(describing: date))]) } } - public static func parse_webFile(_ reader: BufferReader) -> WebFile? { + public static func parse_sentEncryptedFile(_ reader: BufferReader) -> SentEncryptedMessage? { var _1: Int32? _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: Api.storage.FileType? + var _2: Api.EncryptedFile? if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.storage.FileType + _2 = Api.parse(reader, signature: signature) as? Api.EncryptedFile } - var _4: Int32? - _4 = reader.readInt32() - var _5: Buffer? - _5 = parseBytes(reader) let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.upload.WebFile.webFile(size: _1!, mimeType: _2!, fileType: _3!, mtime: _4!, bytes: _5!) + if _c1 && _c2 { + return Api.messages.SentEncryptedMessage.sentEncryptedFile(date: _1!, file: _2!) + } + else { + return nil + } + } + public static func parse_sentEncryptedMessage(_ reader: BufferReader) -> SentEncryptedMessage? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.messages.SentEncryptedMessage.sentEncryptedMessage(date: _1!) } else { return nil @@ -1202,17 +244,21 @@ public extension Api.upload { } } -public extension Api.users { - enum UserFull: TypeConstructorDescription { - case userFull(fullUser: Api.UserFull, chats: [Api.Chat], users: [Api.User]) +public extension Api.messages { + enum SponsoredMessages: TypeConstructorDescription { + case sponsoredMessages(messages: [Api.SponsoredMessage], chats: [Api.Chat], users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .userFull(let fullUser, let chats, let users): + case .sponsoredMessages(let messages, let chats, let users): if boxed { - buffer.appendInt32(997004590) + buffer.appendInt32(1705297877) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) } - fullUser.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(chats.count)) for item in chats { @@ -1229,15 +275,15 @@ public extension Api.users { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .userFull(let fullUser, let chats, let users): - return ("userFull", [("fullUser", String(describing: fullUser)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .sponsoredMessages(let messages, let chats, let users): + return ("sponsoredMessages", [("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) } } - public static func parse_userFull(_ reader: BufferReader) -> UserFull? { - var _1: Api.UserFull? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.UserFull + public static func parse_sponsoredMessages(_ reader: BufferReader) -> SponsoredMessages? { + var _1: [Api.SponsoredMessage]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SponsoredMessage.self) } var _2: [Api.Chat]? if let _ = reader.readInt32() { @@ -1251,7 +297,1223 @@ public extension Api.users { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.users.UserFull.userFull(fullUser: _1!, chats: _2!, users: _3!) + return Api.messages.SponsoredMessages.sponsoredMessages(messages: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum StickerSet: TypeConstructorDescription { + case stickerSet(set: Api.StickerSet, packs: [Api.StickerPack], documents: [Api.Document]) + case stickerSetNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stickerSet(let set, let packs, let documents): + if boxed { + buffer.appendInt32(-1240849242) + } + set.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(packs.count)) + for item in packs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents.count)) + for item in documents { + item.serialize(buffer, true) + } + break + case .stickerSetNotModified: + if boxed { + buffer.appendInt32(-738646805) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stickerSet(let set, let packs, let documents): + return ("stickerSet", [("set", String(describing: set)), ("packs", String(describing: packs)), ("documents", String(describing: documents))]) + case .stickerSetNotModified: + return ("stickerSetNotModified", []) + } + } + + public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { + var _1: Api.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StickerSet + } + var _2: [Api.StickerPack]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + } + var _3: [Api.Document]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.StickerSet.stickerSet(set: _1!, packs: _2!, documents: _3!) + } + else { + return nil + } + } + public static func parse_stickerSetNotModified(_ reader: BufferReader) -> StickerSet? { + return Api.messages.StickerSet.stickerSetNotModified + } + + } +} +public extension Api.messages { + enum StickerSetInstallResult: TypeConstructorDescription { + case stickerSetInstallResultArchive(sets: [Api.StickerSetCovered]) + case stickerSetInstallResultSuccess + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stickerSetInstallResultArchive(let sets): + if boxed { + buffer.appendInt32(904138920) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sets.count)) + for item in sets { + item.serialize(buffer, true) + } + break + case .stickerSetInstallResultSuccess: + if boxed { + buffer.appendInt32(946083368) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stickerSetInstallResultArchive(let sets): + return ("stickerSetInstallResultArchive", [("sets", String(describing: sets))]) + case .stickerSetInstallResultSuccess: + return ("stickerSetInstallResultSuccess", []) + } + } + + public static func parse_stickerSetInstallResultArchive(_ reader: BufferReader) -> StickerSetInstallResult? { + var _1: [Api.StickerSetCovered]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.messages.StickerSetInstallResult.stickerSetInstallResultArchive(sets: _1!) + } + else { + return nil + } + } + public static func parse_stickerSetInstallResultSuccess(_ reader: BufferReader) -> StickerSetInstallResult? { + return Api.messages.StickerSetInstallResult.stickerSetInstallResultSuccess + } + + } +} +public extension Api.messages { + enum Stickers: TypeConstructorDescription { + case stickers(hash: Int64, stickers: [Api.Document]) + case stickersNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stickers(let hash, let stickers): + if boxed { + buffer.appendInt32(816245886) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stickers.count)) + for item in stickers { + item.serialize(buffer, true) + } + break + case .stickersNotModified: + if boxed { + buffer.appendInt32(-244016606) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stickers(let hash, let stickers): + return ("stickers", [("hash", String(describing: hash)), ("stickers", String(describing: stickers))]) + case .stickersNotModified: + return ("stickersNotModified", []) + } + } + + public static func parse_stickers(_ reader: BufferReader) -> Stickers? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.Document]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.Stickers.stickers(hash: _1!, stickers: _2!) + } + else { + return nil + } + } + public static func parse_stickersNotModified(_ reader: BufferReader) -> Stickers? { + return Api.messages.Stickers.stickersNotModified + } + + } +} +public extension Api.messages { + enum TranscribedAudio: TypeConstructorDescription { + case transcribedAudio(flags: Int32, transcriptionId: Int64, text: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .transcribedAudio(let flags, let transcriptionId, let text): + if boxed { + buffer.appendInt32(-1821037486) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(transcriptionId, buffer: buffer, boxed: false) + serializeString(text, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .transcribedAudio(let flags, let transcriptionId, let text): + return ("transcribedAudio", [("flags", String(describing: flags)), ("transcriptionId", String(describing: transcriptionId)), ("text", String(describing: text))]) + } + } + + public static func parse_transcribedAudio(_ reader: BufferReader) -> TranscribedAudio? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: String? + _3 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.messages.TranscribedAudio.transcribedAudio(flags: _1!, transcriptionId: _2!, text: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum TranslatedText: TypeConstructorDescription { + case translateNoResult + case translateResultText(text: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .translateNoResult: + if boxed { + buffer.appendInt32(1741309751) + } + + break + case .translateResultText(let text): + if boxed { + buffer.appendInt32(-1575684144) + } + serializeString(text, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .translateNoResult: + return ("translateNoResult", []) + case .translateResultText(let text): + return ("translateResultText", [("text", String(describing: text))]) + } + } + + public static func parse_translateNoResult(_ reader: BufferReader) -> TranslatedText? { + return Api.messages.TranslatedText.translateNoResult + } + public static func parse_translateResultText(_ reader: BufferReader) -> TranslatedText? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.messages.TranslatedText.translateResultText(text: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum VotesList: TypeConstructorDescription { + case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + if boxed { + buffer.appendInt32(136574537) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(votes.count)) + for item in votes { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .votesList(let flags, let count, let votes, let users, let nextOffset): + return ("votesList", [("flags", String(describing: flags)), ("count", String(describing: count)), ("votes", String(describing: votes)), ("users", String(describing: users)), ("nextOffset", String(describing: nextOffset))]) + } + } + + public static func parse_votesList(_ reader: BufferReader) -> VotesList? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.MessageUserVote]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserVote.self) + } + var _4: [Api.User]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _5: String? + if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.messages.VotesList.votesList(flags: _1!, count: _2!, votes: _3!, users: _4!, nextOffset: _5) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum BankCardData: TypeConstructorDescription { + case bankCardData(title: String, openUrls: [Api.BankCardOpenUrl]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .bankCardData(let title, let openUrls): + if boxed { + buffer.appendInt32(1042605427) + } + serializeString(title, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(openUrls.count)) + for item in openUrls { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .bankCardData(let title, let openUrls): + return ("bankCardData", [("title", String(describing: title)), ("openUrls", String(describing: openUrls))]) + } + } + + public static func parse_bankCardData(_ reader: BufferReader) -> BankCardData? { + var _1: String? + _1 = parseString(reader) + var _2: [Api.BankCardOpenUrl]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BankCardOpenUrl.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.payments.BankCardData.bankCardData(title: _1!, openUrls: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum ExportedInvoice: TypeConstructorDescription { + case exportedInvoice(url: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .exportedInvoice(let url): + if boxed { + buffer.appendInt32(-1362048039) + } + serializeString(url, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .exportedInvoice(let url): + return ("exportedInvoice", [("url", String(describing: url))]) + } + } + + public static func parse_exportedInvoice(_ reader: BufferReader) -> ExportedInvoice? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.payments.ExportedInvoice.exportedInvoice(url: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum PaymentForm: TypeConstructorDescription { + case paymentForm(flags: Int32, formId: Int64, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, providerId: Int64, url: String, nativeProvider: String?, nativeParams: Api.DataJSON?, additionalMethods: [Api.PaymentFormMethod]?, savedInfo: Api.PaymentRequestedInfo?, savedCredentials: [Api.PaymentSavedCredentials]?, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): + if boxed { + buffer.appendInt32(-1610250415) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(formId, buffer: buffer, boxed: false) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(description, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} + invoice.serialize(buffer, true) + serializeInt64(providerId, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 4) != 0 {serializeString(nativeProvider!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {nativeParams!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(additionalMethods!.count)) + for item in additionalMethods! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(savedCredentials!.count)) + for item in savedCredentials! { + 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 .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): + return ("paymentForm", [("flags", String(describing: flags)), ("formId", String(describing: formId)), ("botId", String(describing: botId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("invoice", String(describing: invoice)), ("providerId", String(describing: providerId)), ("url", String(describing: url)), ("nativeProvider", String(describing: nativeProvider)), ("nativeParams", String(describing: nativeParams)), ("additionalMethods", String(describing: additionalMethods)), ("savedInfo", String(describing: savedInfo)), ("savedCredentials", String(describing: savedCredentials)), ("users", String(describing: users))]) + } + } + + public static func parse_paymentForm(_ reader: BufferReader) -> PaymentForm? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: Api.WebDocument? + if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.WebDocument + } } + var _7: Api.Invoice? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.Invoice + } + var _8: Int64? + _8 = reader.readInt64() + var _9: String? + _9 = parseString(reader) + var _10: String? + if Int(_1!) & Int(1 << 4) != 0 {_10 = parseString(reader) } + var _11: Api.DataJSON? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.DataJSON + } } + var _12: [Api.PaymentFormMethod]? + if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() { + _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentFormMethod.self) + } } + var _13: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } + var _14: [Api.PaymentSavedCredentials]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentSavedCredentials.self) + } } + var _15: [Api.User]? + if let _ = reader.readInt32() { + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 5) == 0) || _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 4) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 6) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 0) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 1) == 0) || _14 != nil + let _c15 = _15 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { + return Api.payments.PaymentForm.paymentForm(flags: _1!, formId: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, providerId: _8!, url: _9!, nativeProvider: _10, nativeParams: _11, additionalMethods: _12, savedInfo: _13, savedCredentials: _14, users: _15!) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum PaymentReceipt: TypeConstructorDescription { + case paymentReceipt(flags: Int32, date: Int32, botId: Int64, providerId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, info: Api.PaymentRequestedInfo?, shipping: Api.ShippingOption?, tipAmount: Int64?, currency: String, totalAmount: Int64, credentialsTitle: String, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentReceipt(let flags, let date, let botId, let providerId, let title, let description, let photo, let invoice, let info, let shipping, let tipAmount, let currency, let totalAmount, let credentialsTitle, let users): + if boxed { + buffer.appendInt32(1891958275) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeInt64(providerId, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(description, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {photo!.serialize(buffer, true)} + invoice.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {info!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {shipping!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {serializeInt64(tipAmount!, buffer: buffer, boxed: false)} + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(totalAmount, buffer: buffer, boxed: false) + serializeString(credentialsTitle, 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 .paymentReceipt(let flags, let date, let botId, let providerId, let title, let description, let photo, let invoice, let info, let shipping, let tipAmount, let currency, let totalAmount, let credentialsTitle, let users): + return ("paymentReceipt", [("flags", String(describing: flags)), ("date", String(describing: date)), ("botId", String(describing: botId)), ("providerId", String(describing: providerId)), ("title", String(describing: title)), ("description", String(describing: description)), ("photo", String(describing: photo)), ("invoice", String(describing: invoice)), ("info", String(describing: info)), ("shipping", String(describing: shipping)), ("tipAmount", String(describing: tipAmount)), ("currency", String(describing: currency)), ("totalAmount", String(describing: totalAmount)), ("credentialsTitle", String(describing: credentialsTitle)), ("users", String(describing: users))]) + } + } + + public static func parse_paymentReceipt(_ reader: BufferReader) -> PaymentReceipt? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + var _4: Int64? + _4 = reader.readInt64() + var _5: String? + _5 = parseString(reader) + var _6: String? + _6 = parseString(reader) + var _7: Api.WebDocument? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.WebDocument + } } + var _8: Api.Invoice? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.Invoice + } + var _9: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } + var _10: Api.ShippingOption? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.ShippingOption + } } + var _11: Int64? + if Int(_1!) & Int(1 << 3) != 0 {_11 = reader.readInt64() } + var _12: String? + _12 = parseString(reader) + var _13: Int64? + _13 = reader.readInt64() + var _14: String? + _14 = parseString(reader) + var _15: [Api.User]? + if let _ = reader.readInt32() { + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil + let _c8 = _8 != nil + let _c9 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 1) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 3) == 0) || _11 != nil + let _c12 = _12 != nil + let _c13 = _13 != nil + let _c14 = _14 != nil + let _c15 = _15 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { + return Api.payments.PaymentReceipt.paymentReceipt(flags: _1!, date: _2!, botId: _3!, providerId: _4!, title: _5!, description: _6!, photo: _7, invoice: _8!, info: _9, shipping: _10, tipAmount: _11, currency: _12!, totalAmount: _13!, credentialsTitle: _14!, users: _15!) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum PaymentResult: TypeConstructorDescription { + case paymentResult(updates: Api.Updates) + case paymentVerificationNeeded(url: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentResult(let updates): + if boxed { + buffer.appendInt32(1314881805) + } + updates.serialize(buffer, true) + break + case .paymentVerificationNeeded(let url): + if boxed { + buffer.appendInt32(-666824391) + } + serializeString(url, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paymentResult(let updates): + return ("paymentResult", [("updates", String(describing: updates))]) + case .paymentVerificationNeeded(let url): + return ("paymentVerificationNeeded", [("url", String(describing: url))]) + } + } + + public static func parse_paymentResult(_ reader: BufferReader) -> PaymentResult? { + var _1: Api.Updates? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Updates + } + let _c1 = _1 != nil + if _c1 { + return Api.payments.PaymentResult.paymentResult(updates: _1!) + } + else { + return nil + } + } + public static func parse_paymentVerificationNeeded(_ reader: BufferReader) -> PaymentResult? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.payments.PaymentResult.paymentVerificationNeeded(url: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum SavedInfo: TypeConstructorDescription { + case savedInfo(flags: Int32, savedInfo: Api.PaymentRequestedInfo?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .savedInfo(let flags, let savedInfo): + if boxed { + buffer.appendInt32(-74456004) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .savedInfo(let flags, let savedInfo): + return ("savedInfo", [("flags", String(describing: flags)), ("savedInfo", String(describing: savedInfo))]) + } + } + + public static func parse_savedInfo(_ reader: BufferReader) -> SavedInfo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + if _c1 && _c2 { + return Api.payments.SavedInfo.savedInfo(flags: _1!, savedInfo: _2) + } + else { + return nil + } + } + + } +} +public extension Api.payments { + enum ValidatedRequestedInfo: TypeConstructorDescription { + case validatedRequestedInfo(flags: Int32, id: String?, shippingOptions: [Api.ShippingOption]?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .validatedRequestedInfo(let flags, let id, let shippingOptions): + if boxed { + buffer.appendInt32(-784000893) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(id!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(shippingOptions!.count)) + for item in shippingOptions! { + item.serialize(buffer, true) + }} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .validatedRequestedInfo(let flags, let id, let shippingOptions): + return ("validatedRequestedInfo", [("flags", String(describing: flags)), ("id", String(describing: id)), ("shippingOptions", String(describing: shippingOptions))]) + } + } + + public static func parse_validatedRequestedInfo(_ reader: BufferReader) -> ValidatedRequestedInfo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: [Api.ShippingOption]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ShippingOption.self) + } } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.payments.ValidatedRequestedInfo.validatedRequestedInfo(flags: _1!, id: _2, shippingOptions: _3) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum ExportedGroupCallInvite: TypeConstructorDescription { + case exportedGroupCallInvite(link: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .exportedGroupCallInvite(let link): + if boxed { + buffer.appendInt32(541839704) + } + serializeString(link, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .exportedGroupCallInvite(let link): + return ("exportedGroupCallInvite", [("link", String(describing: link))]) + } + } + + public static func parse_exportedGroupCallInvite(_ reader: BufferReader) -> ExportedGroupCallInvite? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.phone.ExportedGroupCallInvite.exportedGroupCallInvite(link: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum GroupCall: TypeConstructorDescription { + case groupCall(call: Api.GroupCall, participants: [Api.GroupCallParticipant], participantsNextOffset: String, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .groupCall(let call, let participants, let participantsNextOffset, let chats, let users): + if boxed { + buffer.appendInt32(-1636664659) + } + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(participants.count)) + for item in participants { + item.serialize(buffer, true) + } + serializeString(participantsNextOffset, 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 .groupCall(let call, let participants, let participantsNextOffset, let chats, let users): + return ("groupCall", [("call", String(describing: call)), ("participants", String(describing: participants)), ("participantsNextOffset", String(describing: participantsNextOffset)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_groupCall(_ reader: BufferReader) -> GroupCall? { + var _1: Api.GroupCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GroupCall + } + var _2: [Api.GroupCallParticipant]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) + } + var _3: String? + _3 = parseString(reader) + var _4: [Api.Chat]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + 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 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.phone.GroupCall.groupCall(call: _1!, participants: _2!, participantsNextOffset: _3!, chats: _4!, users: _5!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum GroupCallStreamChannels: TypeConstructorDescription { + case groupCallStreamChannels(channels: [Api.GroupCallStreamChannel]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .groupCallStreamChannels(let channels): + if boxed { + buffer.appendInt32(-790330702) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(channels.count)) + for item in channels { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .groupCallStreamChannels(let channels): + return ("groupCallStreamChannels", [("channels", String(describing: channels))]) + } + } + + public static func parse_groupCallStreamChannels(_ reader: BufferReader) -> GroupCallStreamChannels? { + var _1: [Api.GroupCallStreamChannel]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallStreamChannel.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.phone.GroupCallStreamChannels.groupCallStreamChannels(channels: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum GroupCallStreamRtmpUrl: TypeConstructorDescription { + case groupCallStreamRtmpUrl(url: String, key: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .groupCallStreamRtmpUrl(let url, let key): + if boxed { + buffer.appendInt32(767505458) + } + serializeString(url, buffer: buffer, boxed: false) + serializeString(key, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .groupCallStreamRtmpUrl(let url, let key): + return ("groupCallStreamRtmpUrl", [("url", String(describing: url)), ("key", String(describing: key))]) + } + } + + public static func parse_groupCallStreamRtmpUrl(_ reader: BufferReader) -> GroupCallStreamRtmpUrl? { + var _1: String? + _1 = parseString(reader) + var _2: String? + _2 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.phone.GroupCallStreamRtmpUrl.groupCallStreamRtmpUrl(url: _1!, key: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum GroupParticipants: TypeConstructorDescription { + case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], nextOffset: String, chats: [Api.Chat], users: [Api.User], version: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version): + if boxed { + buffer.appendInt32(-193506890) + } + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(participants.count)) + for item in participants { + item.serialize(buffer, true) + } + 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) + } + serializeInt32(version, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .groupParticipants(let count, let participants, let nextOffset, let chats, let users, let version): + return ("groupParticipants", [("count", String(describing: count)), ("participants", String(describing: participants)), ("nextOffset", String(describing: nextOffset)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("version", String(describing: version))]) + } + } + + public static func parse_groupParticipants(_ reader: BufferReader) -> GroupParticipants? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.GroupCallParticipant]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallParticipant.self) + } + var _3: String? + _3 = parseString(reader) + var _4: [Api.Chat]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _5: [Api.User]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _6: Int32? + _6 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.phone.GroupParticipants.groupParticipants(count: _1!, participants: _2!, nextOffset: _3!, chats: _4!, users: _5!, version: _6!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum JoinAsPeers: TypeConstructorDescription { + case joinAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .joinAsPeers(let peers, let chats, let users): + if boxed { + buffer.appendInt32(-1343921601) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + item.serialize(buffer, true) + } + 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 .joinAsPeers(let peers, let chats, let users): + return ("joinAsPeers", [("peers", String(describing: peers)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_joinAsPeers(_ reader: BufferReader) -> JoinAsPeers? { + var _1: [Api.Peer]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.phone.JoinAsPeers.joinAsPeers(peers: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum PhoneCall: TypeConstructorDescription { + case phoneCall(phoneCall: Api.PhoneCall, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCall(let phoneCall, let users): + if boxed { + buffer.appendInt32(-326966976) + } + phoneCall.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 .phoneCall(let phoneCall, let users): + return ("phoneCall", [("phoneCall", String(describing: phoneCall)), ("users", String(describing: users))]) + } + } + + public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { + var _1: Api.PhoneCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.phone.PhoneCall.phoneCall(phoneCall: _1!, users: _2!) + } + else { + return nil + } + } + + } +} +public extension Api.photos { + enum Photo: TypeConstructorDescription { + case photo(photo: Api.Photo, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .photo(let photo, let users): + if boxed { + buffer.appendInt32(539045032) + } + photo.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 .photo(let photo, let users): + return ("photo", [("photo", String(describing: photo)), ("users", String(describing: users))]) + } + } + + public static func parse_photo(_ reader: BufferReader) -> Photo? { + var _1: Api.Photo? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Photo + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.photos.Photo.photo(photo: _1!, users: _2!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index d5594303ec..58fa0773fb 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1,7475 +1,1262 @@ -public extension Api.functions.account { - static func acceptAuthorization(botId: Int64, scope: String, publicKey: String, valueHashes: [Api.SecureValueHash], credentials: Api.SecureCredentialsEncrypted) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-202552205) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeString(scope, buffer: buffer, boxed: false) - serializeString(publicKey, buffer: buffer, boxed: false) +public extension Api.photos { + enum Photos: TypeConstructorDescription { + case photos(photos: [Api.Photo], users: [Api.User]) + case photosSlice(count: Int32, photos: [Api.Photo], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .photos(let photos, let users): + if boxed { + buffer.appendInt32(-1916114267) + } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(valueHashes.count)) - for item in valueHashes { + buffer.appendInt32(Int32(photos.count)) + for item in photos { item.serialize(buffer, true) } - credentials.serialize(buffer, true) - return (FunctionDescription(name: "account.acceptAuthorization", parameters: [("botId", String(describing: botId)), ("scope", String(describing: scope)), ("publicKey", String(describing: publicKey)), ("valueHashes", String(describing: valueHashes)), ("credentials", String(describing: credentials))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func cancelPasswordEmail() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1043606090) - - return (FunctionDescription(name: "account.cancelPasswordEmail", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func changeAuthorizationSettings(flags: Int32, hash: Int64, encryptedRequestsDisabled: Api.Bool?, callRequestsDisabled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1089766498) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {encryptedRequestsDisabled!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {callRequestsDisabled!.serialize(buffer, true)} - return (FunctionDescription(name: "account.changeAuthorizationSettings", parameters: [("flags", String(describing: flags)), ("hash", String(describing: hash)), ("encryptedRequestsDisabled", String(describing: encryptedRequestsDisabled)), ("callRequestsDisabled", String(describing: callRequestsDisabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func changePhone(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1891839707) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - serializeString(phoneCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.changePhone", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in - let reader = BufferReader(buffer) - var result: Api.User? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.User - } - return result - }) - } -} -public extension Api.functions.account { - static func checkUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(655677548) - serializeString(username, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.checkUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func confirmPasswordEmail(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1881204448) - serializeString(code, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.confirmPasswordEmail", parameters: [("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func confirmPhone(phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1596029123) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - serializeString(phoneCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.confirmPhone", parameters: [("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func createTheme(flags: Int32, slug: String, title: String, document: Api.InputDocument?, settings: [Api.InputThemeSettings]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1697530880) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(slug, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(settings!.count)) - for item in settings! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "account.createTheme", parameters: [("flags", String(describing: flags)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in - let reader = BufferReader(buffer) - var result: Api.Theme? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Theme - } - return result - }) - } -} -public extension Api.functions.account { - static func declinePasswordReset() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1284770294) - - return (FunctionDescription(name: "account.declinePasswordReset", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func deleteAccount(flags: Int32, reason: String, password: Api.InputCheckPasswordSRP?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1564422284) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(reason, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {password!.serialize(buffer, true)} - return (FunctionDescription(name: "account.deleteAccount", parameters: [("flags", String(describing: flags)), ("reason", String(describing: reason)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func deleteSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1199522741) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(types.count)) - for item in types { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "account.deleteSecureValue", parameters: [("types", String(describing: types))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func finishTakeoutSession(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(489050862) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.finishTakeoutSession", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func getAccountTTL() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(150761757) - - return (FunctionDescription(name: "account.getAccountTTL", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AccountDaysTTL? in - let reader = BufferReader(buffer) - var result: Api.AccountDaysTTL? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.AccountDaysTTL - } - return result - }) - } -} -public extension Api.functions.account { - static func getAllSecureValues() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SecureValue]>) { - let buffer = Buffer() - buffer.appendInt32(-1299661699) - - return (FunctionDescription(name: "account.getAllSecureValues", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SecureValue]? in - let reader = BufferReader(buffer) - var result: [Api.SecureValue]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) - } - return result - }) - } -} -public extension Api.functions.account { - static func getAuthorizationForm(botId: Int64, scope: String, publicKey: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1456907910) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeString(scope, buffer: buffer, boxed: false) - serializeString(publicKey, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getAuthorizationForm", parameters: [("botId", String(describing: botId)), ("scope", String(describing: scope)), ("publicKey", String(describing: publicKey))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.AuthorizationForm? in - let reader = BufferReader(buffer) - var result: Api.account.AuthorizationForm? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.AuthorizationForm - } - return result - }) - } -} -public extension Api.functions.account { - static func getAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-484392616) - - return (FunctionDescription(name: "account.getAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Authorizations? in - let reader = BufferReader(buffer) - var result: Api.account.Authorizations? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.Authorizations - } - return result - }) - } -} -public extension Api.functions.account { - static func getAutoDownloadSettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1457130303) - - return (FunctionDescription(name: "account.getAutoDownloadSettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.AutoDownloadSettings? in - let reader = BufferReader(buffer) - var result: Api.account.AutoDownloadSettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.AutoDownloadSettings - } - return result - }) - } -} -public extension Api.functions.account { - static func getChatThemes(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-700916087) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getChatThemes", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Themes? in - let reader = BufferReader(buffer) - var result: Api.account.Themes? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.Themes - } - return result - }) - } -} -public extension Api.functions.account { - static func getContactSignUpNotification() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1626880216) - - return (FunctionDescription(name: "account.getContactSignUpNotification", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func getContentSettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1952756306) - - return (FunctionDescription(name: "account.getContentSettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.ContentSettings? in - let reader = BufferReader(buffer) - var result: Api.account.ContentSettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.ContentSettings - } - return result - }) - } -} -public extension Api.functions.account { - static func getGlobalPrivacySettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-349483786) - - return (FunctionDescription(name: "account.getGlobalPrivacySettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.GlobalPrivacySettings? in - let reader = BufferReader(buffer) - var result: Api.GlobalPrivacySettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.GlobalPrivacySettings - } - return result - }) - } -} -public extension Api.functions.account { - static func getMultiWallPapers(wallpapers: [Api.InputWallPaper]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.WallPaper]>) { - let buffer = Buffer() - buffer.appendInt32(1705865692) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(wallpapers.count)) - for item in wallpapers { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "account.getMultiWallPapers", parameters: [("wallpapers", String(describing: wallpapers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.WallPaper]? in - let reader = BufferReader(buffer) - var result: [Api.WallPaper]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.WallPaper.self) - } - return result - }) - } -} -public extension Api.functions.account { - static func getNotifyExceptions(flags: Int32, peer: Api.InputNotifyPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1398240377) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)} - return (FunctionDescription(name: "account.getNotifyExceptions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.account { - static func getNotifySettings(peer: Api.InputNotifyPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(313765169) - peer.serialize(buffer, true) - return (FunctionDescription(name: "account.getNotifySettings", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.PeerNotifySettings? in - let reader = BufferReader(buffer) - var result: Api.PeerNotifySettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings - } - return result - }) - } -} -public extension Api.functions.account { - static func getPassword() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1418342645) - - return (FunctionDescription(name: "account.getPassword", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Password? in - let reader = BufferReader(buffer) - var result: Api.account.Password? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.Password - } - return result - }) - } -} -public extension Api.functions.account { - static func getPasswordSettings(password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1663767815) - password.serialize(buffer, true) - return (FunctionDescription(name: "account.getPasswordSettings", parameters: [("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PasswordSettings? in - let reader = BufferReader(buffer) - var result: Api.account.PasswordSettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.PasswordSettings - } - return result - }) - } -} -public extension Api.functions.account { - static func getPrivacy(key: Api.InputPrivacyKey) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-623130288) - key.serialize(buffer, true) - return (FunctionDescription(name: "account.getPrivacy", parameters: [("key", String(describing: key))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PrivacyRules? in - let reader = BufferReader(buffer) - var result: Api.account.PrivacyRules? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.PrivacyRules - } - return result - }) - } -} -public extension Api.functions.account { - static func getSavedRingtones(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-510647672) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getSavedRingtones", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtones? in - let reader = BufferReader(buffer) - var result: Api.account.SavedRingtones? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtones - } - return result - }) - } -} -public extension Api.functions.account { - static func getSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SecureValue]>) { - let buffer = Buffer() - buffer.appendInt32(1936088002) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(types.count)) - for item in types { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "account.getSecureValue", parameters: [("types", String(describing: types))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SecureValue]? in - let reader = BufferReader(buffer) - var result: [Api.SecureValue]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) - } - return result - }) - } -} -public extension Api.functions.account { - static func getTheme(format: String, theme: Api.InputTheme, documentId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1919060949) - serializeString(format, buffer: buffer, boxed: false) - theme.serialize(buffer, true) - serializeInt64(documentId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getTheme", parameters: [("format", String(describing: format)), ("theme", String(describing: theme)), ("documentId", String(describing: documentId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in - let reader = BufferReader(buffer) - var result: Api.Theme? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Theme - } - return result - }) - } -} -public extension Api.functions.account { - static func getThemes(format: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1913054296) - serializeString(format, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getThemes", parameters: [("format", String(describing: format)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Themes? in - let reader = BufferReader(buffer) - var result: Api.account.Themes? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.Themes - } - return result - }) - } -} -public extension Api.functions.account { - static func getTmpPassword(password: Api.InputCheckPasswordSRP, period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1151208273) - password.serialize(buffer, true) - serializeInt32(period, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getTmpPassword", parameters: [("password", String(describing: password)), ("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.TmpPassword? in - let reader = BufferReader(buffer) - var result: Api.account.TmpPassword? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.TmpPassword - } - return result - }) - } -} -public extension Api.functions.account { - static func getWallPaper(wallpaper: Api.InputWallPaper) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-57811990) - wallpaper.serialize(buffer, true) - return (FunctionDescription(name: "account.getWallPaper", parameters: [("wallpaper", String(describing: wallpaper))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WallPaper? in - let reader = BufferReader(buffer) - var result: Api.WallPaper? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.WallPaper - } - return result - }) - } -} -public extension Api.functions.account { - static func getWallPapers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(127302966) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.getWallPapers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.WallPapers? in - let reader = BufferReader(buffer) - var result: Api.account.WallPapers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.WallPapers - } - return result - }) - } -} -public extension Api.functions.account { - static func getWebAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(405695855) - - return (FunctionDescription(name: "account.getWebAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.WebAuthorizations? in - let reader = BufferReader(buffer) - var result: Api.account.WebAuthorizations? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.WebAuthorizations - } - return result - }) - } -} -public extension Api.functions.account { - static func initTakeoutSession(flags: Int32, fileMaxSize: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1896617296) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 5) != 0 {serializeInt64(fileMaxSize!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "account.initTakeoutSession", parameters: [("flags", String(describing: flags)), ("fileMaxSize", String(describing: fileMaxSize))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Takeout? in - let reader = BufferReader(buffer) - var result: Api.account.Takeout? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.Takeout - } - return result - }) - } -} -public extension Api.functions.account { - static func installTheme(flags: Int32, theme: Api.InputTheme?, format: String?, baseTheme: Api.BaseTheme?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-953697477) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {theme!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(format!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {baseTheme!.serialize(buffer, true)} - return (FunctionDescription(name: "account.installTheme", parameters: [("flags", String(describing: flags)), ("theme", String(describing: theme)), ("format", String(describing: format)), ("baseTheme", String(describing: baseTheme))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func installWallPaper(wallpaper: Api.InputWallPaper, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-18000023) - wallpaper.serialize(buffer, true) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.installWallPaper", parameters: [("wallpaper", String(describing: wallpaper)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func registerDevice(flags: Int32, tokenType: Int32, token: String, appSandbox: Api.Bool, secret: Buffer, otherUids: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-326762118) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(tokenType, buffer: buffer, boxed: false) - serializeString(token, buffer: buffer, boxed: false) - appSandbox.serialize(buffer, true) - serializeBytes(secret, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUids.count)) - for item in otherUids { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "account.registerDevice", parameters: [("flags", String(describing: flags)), ("tokenType", String(describing: tokenType)), ("token", String(describing: token)), ("appSandbox", String(describing: appSandbox)), ("secret", String(describing: secret)), ("otherUids", String(describing: otherUids))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func reportPeer(peer: Api.InputPeer, reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-977650298) - peer.serialize(buffer, true) - reason.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.reportPeer", parameters: [("peer", String(describing: peer)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func reportProfilePhoto(peer: Api.InputPeer, photoId: Api.InputPhoto, reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-91437323) - peer.serialize(buffer, true) - photoId.serialize(buffer, true) - reason.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.reportProfilePhoto", parameters: [("peer", String(describing: peer)), ("photoId", String(describing: photoId)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resendPasswordEmail() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2055154197) - - return (FunctionDescription(name: "account.resendPasswordEmail", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resetAuthorization(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-545786948) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.resetAuthorization", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resetNotifySettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-612493497) - - return (FunctionDescription(name: "account.resetNotifySettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resetPassword() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1828139493) - - return (FunctionDescription(name: "account.resetPassword", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.ResetPasswordResult? in - let reader = BufferReader(buffer) - var result: Api.account.ResetPasswordResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.ResetPasswordResult - } - return result - }) - } -} -public extension Api.functions.account { - static func resetWallPapers() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1153722364) - - return (FunctionDescription(name: "account.resetWallPapers", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resetWebAuthorization(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(755087855) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.resetWebAuthorization", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func resetWebAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1747789204) - - return (FunctionDescription(name: "account.resetWebAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func saveAutoDownloadSettings(flags: Int32, settings: Api.AutoDownloadSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1995661875) - serializeInt32(flags, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.saveAutoDownloadSettings", parameters: [("flags", String(describing: flags)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func saveRingtone(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1038768899) - id.serialize(buffer, true) - unsave.serialize(buffer, true) - return (FunctionDescription(name: "account.saveRingtone", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtone? in - let reader = BufferReader(buffer) - var result: Api.account.SavedRingtone? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtone - } - return result - }) - } -} -public extension Api.functions.account { - static func saveSecureValue(value: Api.InputSecureValue, secureSecretId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1986010339) - value.serialize(buffer, true) - serializeInt64(secureSecretId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.saveSecureValue", parameters: [("value", String(describing: value)), ("secureSecretId", String(describing: secureSecretId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SecureValue? in - let reader = BufferReader(buffer) - var result: Api.SecureValue? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.SecureValue - } - return result - }) - } -} -public extension Api.functions.account { - static func saveTheme(theme: Api.InputTheme, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-229175188) - theme.serialize(buffer, true) - unsave.serialize(buffer, true) - return (FunctionDescription(name: "account.saveTheme", parameters: [("theme", String(describing: theme)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func saveWallPaper(wallpaper: Api.InputWallPaper, unsave: Api.Bool, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1817860919) - wallpaper.serialize(buffer, true) - unsave.serialize(buffer, true) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.saveWallPaper", parameters: [("wallpaper", String(describing: wallpaper)), ("unsave", String(describing: unsave)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func sendChangePhoneCode(phoneNumber: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2108208411) - serializeString(phoneNumber, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.sendChangePhoneCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in - let reader = BufferReader(buffer) - var result: Api.auth.SentCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.SentCode - } - return result - }) - } -} -public extension Api.functions.account { - static func sendConfirmPhoneCode(hash: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(457157256) - serializeString(hash, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.sendConfirmPhoneCode", parameters: [("hash", String(describing: hash)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in - let reader = BufferReader(buffer) - var result: Api.auth.SentCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.SentCode - } - return result - }) - } -} -public extension Api.functions.account { - static func sendVerifyEmailCode(email: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1880182943) - serializeString(email, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.sendVerifyEmailCode", parameters: [("email", String(describing: email))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SentEmailCode? in - let reader = BufferReader(buffer) - var result: Api.account.SentEmailCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.SentEmailCode - } - return result - }) - } -} -public extension Api.functions.account { - static func sendVerifyPhoneCode(phoneNumber: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1516022023) - serializeString(phoneNumber, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.sendVerifyPhoneCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in - let reader = BufferReader(buffer) - var result: Api.auth.SentCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.SentCode - } - return result - }) - } -} -public extension Api.functions.account { - static func setAccountTTL(ttl: Api.AccountDaysTTL) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(608323678) - ttl.serialize(buffer, true) - return (FunctionDescription(name: "account.setAccountTTL", parameters: [("ttl", String(describing: ttl))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func setAuthorizationTTL(authorizationTtlDays: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1081501024) - serializeInt32(authorizationTtlDays, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.setAuthorizationTTL", parameters: [("authorizationTtlDays", String(describing: authorizationTtlDays))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func setContactSignUpNotification(silent: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-806076575) - silent.serialize(buffer, true) - return (FunctionDescription(name: "account.setContactSignUpNotification", parameters: [("silent", String(describing: silent))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func setContentSettings(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1250643605) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.setContentSettings", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func setGlobalPrivacySettings(settings: Api.GlobalPrivacySettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(517647042) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.setGlobalPrivacySettings", parameters: [("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.GlobalPrivacySettings? in - let reader = BufferReader(buffer) - var result: Api.GlobalPrivacySettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.GlobalPrivacySettings - } - return result - }) - } -} -public extension Api.functions.account { - static func setPrivacy(key: Api.InputPrivacyKey, rules: [Api.InputPrivacyRule]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-906486552) - key.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rules.count)) - for item in rules { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "account.setPrivacy", parameters: [("key", String(describing: key)), ("rules", String(describing: rules))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PrivacyRules? in - let reader = BufferReader(buffer) - var result: Api.account.PrivacyRules? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.account.PrivacyRules - } - return result - }) - } -} -public extension Api.functions.account { - static func unregisterDevice(tokenType: Int32, token: String, otherUids: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1779249670) - serializeInt32(tokenType, buffer: buffer, boxed: false) - serializeString(token, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(otherUids.count)) - for item in otherUids { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "account.unregisterDevice", parameters: [("tokenType", String(describing: tokenType)), ("token", String(describing: token)), ("otherUids", String(describing: otherUids))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func updateDeviceLocked(period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(954152242) - serializeInt32(period, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.updateDeviceLocked", parameters: [("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func updateNotifySettings(peer: Api.InputNotifyPeer, settings: Api.InputPeerNotifySettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2067899501) - peer.serialize(buffer, true) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.updateNotifySettings", parameters: [("peer", String(describing: peer)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func updatePasswordSettings(password: Api.InputCheckPasswordSRP, newSettings: Api.account.PasswordInputSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1516564433) - password.serialize(buffer, true) - newSettings.serialize(buffer, true) - return (FunctionDescription(name: "account.updatePasswordSettings", parameters: [("password", String(describing: password)), ("newSettings", String(describing: newSettings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func updateProfile(flags: Int32, firstName: String?, lastName: String?, about: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2018596725) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(firstName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(lastName!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(about!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "account.updateProfile", parameters: [("flags", String(describing: flags)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("about", String(describing: about))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in - let reader = BufferReader(buffer) - var result: Api.User? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.User - } - return result - }) - } -} -public extension Api.functions.account { - static func updateStatus(offline: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1713919532) - offline.serialize(buffer, true) - return (FunctionDescription(name: "account.updateStatus", parameters: [("offline", String(describing: offline))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func updateTheme(flags: Int32, format: String, theme: Api.InputTheme, slug: String?, title: String?, document: Api.InputDocument?, settings: [Api.InputThemeSettings]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(737414348) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(format, buffer: buffer, boxed: false) - theme.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeString(slug!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(settings!.count)) - for item in settings! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "account.updateTheme", parameters: [("flags", String(describing: flags)), ("format", String(describing: format)), ("theme", String(describing: theme)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in - let reader = BufferReader(buffer) - var result: Api.Theme? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Theme - } - return result - }) - } -} -public extension Api.functions.account { - static func updateUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1040964988) - serializeString(username, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.updateUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in - let reader = BufferReader(buffer) - var result: Api.User? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.User - } - return result - }) - } -} -public extension Api.functions.account { - static func uploadRingtone(file: Api.InputFile, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2095414366) - file.serialize(buffer, true) - serializeString(fileName, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.uploadRingtone", parameters: [("file", String(describing: file)), ("fileName", String(describing: fileName)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in - let reader = BufferReader(buffer) - var result: Api.Document? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Document - } - return result - }) - } -} -public extension Api.functions.account { - static func uploadTheme(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(473805619) - serializeInt32(flags, buffer: buffer, boxed: false) - file.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {thumb!.serialize(buffer, true)} - serializeString(fileName, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.uploadTheme", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("thumb", String(describing: thumb)), ("fileName", String(describing: fileName)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in - let reader = BufferReader(buffer) - var result: Api.Document? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Document - } - return result - }) - } -} -public extension Api.functions.account { - static func uploadWallPaper(file: Api.InputFile, mimeType: String, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-578472351) - file.serialize(buffer, true) - serializeString(mimeType, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "account.uploadWallPaper", parameters: [("file", String(describing: file)), ("mimeType", String(describing: mimeType)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WallPaper? in - let reader = BufferReader(buffer) - var result: Api.WallPaper? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.WallPaper - } - return result - }) - } -} -public extension Api.functions.account { - static func verifyEmail(email: String, code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-323339813) - serializeString(email, buffer: buffer, boxed: false) - serializeString(code, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.verifyEmail", parameters: [("email", String(describing: email)), ("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.account { - static func verifyPhone(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1305716726) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - serializeString(phoneCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.verifyPhone", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func acceptLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-392909491) - serializeBytes(token, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.acceptLoginToken", parameters: [("token", String(describing: token))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Authorization? in - let reader = BufferReader(buffer) - var result: Api.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func bindTempAuthKey(permAuthKeyId: Int64, nonce: Int64, expiresAt: Int32, encryptedMessage: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-841733627) - serializeInt64(permAuthKeyId, buffer: buffer, boxed: false) - serializeInt64(nonce, buffer: buffer, boxed: false) - serializeInt32(expiresAt, buffer: buffer, boxed: false) - serializeBytes(encryptedMessage, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.bindTempAuthKey", parameters: [("permAuthKeyId", String(describing: permAuthKeyId)), ("nonce", String(describing: nonce)), ("expiresAt", String(describing: expiresAt)), ("encryptedMessage", String(describing: encryptedMessage))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func cancelCode(phoneNumber: String, phoneCodeHash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(520357240) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.cancelCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func checkPassword(password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-779399914) - password.serialize(buffer, true) - return (FunctionDescription(name: "auth.checkPassword", parameters: [("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func checkRecoveryPassword(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(221691769) - serializeString(code, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.checkRecoveryPassword", parameters: [("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func dropTempAuthKeys(exceptAuthKeys: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1907842680) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(exceptAuthKeys.count)) - for item in exceptAuthKeys { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "auth.dropTempAuthKeys", parameters: [("exceptAuthKeys", String(describing: exceptAuthKeys))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func exportAuthorization(dcId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-440401971) - serializeInt32(dcId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.exportAuthorization", parameters: [("dcId", String(describing: dcId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.ExportedAuthorization? in - let reader = BufferReader(buffer) - var result: Api.auth.ExportedAuthorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.ExportedAuthorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func exportLoginToken(apiId: Int32, apiHash: String, exceptIds: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1210022402) - serializeInt32(apiId, buffer: buffer, boxed: false) - serializeString(apiHash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(exceptIds.count)) - for item in exceptIds { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "auth.exportLoginToken", parameters: [("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("exceptIds", String(describing: exceptIds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoginToken? in - let reader = BufferReader(buffer) - var result: Api.auth.LoginToken? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.LoginToken - } - return result - }) - } -} -public extension Api.functions.auth { - static func importAuthorization(id: Int64, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1518699091) - serializeInt64(id, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.importAuthorization", parameters: [("id", String(describing: id)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func importBotAuthorization(flags: Int32, apiId: Int32, apiHash: String, botAuthToken: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1738800940) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(apiId, buffer: buffer, boxed: false) - serializeString(apiHash, buffer: buffer, boxed: false) - serializeString(botAuthToken, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.importBotAuthorization", parameters: [("flags", String(describing: flags)), ("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("botAuthToken", String(describing: botAuthToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func importLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1783866140) - serializeBytes(token, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.importLoginToken", parameters: [("token", String(describing: token))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoginToken? in - let reader = BufferReader(buffer) - var result: Api.auth.LoginToken? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.LoginToken - } - return result - }) - } -} -public extension Api.functions.auth { - static func logOut() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1047706137) - - return (FunctionDescription(name: "auth.logOut", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoggedOut? in - let reader = BufferReader(buffer) - var result: Api.auth.LoggedOut? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.LoggedOut - } - return result - }) - } -} -public extension Api.functions.auth { - static func recoverPassword(flags: Int32, code: String, newSettings: Api.account.PasswordInputSettings?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(923364464) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(code, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {newSettings!.serialize(buffer, true)} - return (FunctionDescription(name: "auth.recoverPassword", parameters: [("flags", String(describing: flags)), ("code", String(describing: code)), ("newSettings", String(describing: newSettings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func requestPasswordRecovery() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-661144474) - - return (FunctionDescription(name: "auth.requestPasswordRecovery", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.PasswordRecovery? in - let reader = BufferReader(buffer) - var result: Api.auth.PasswordRecovery? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.PasswordRecovery - } - return result - }) - } -} -public extension Api.functions.auth { - static func resendCode(phoneNumber: String, phoneCodeHash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1056025023) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.resendCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in - let reader = BufferReader(buffer) - var result: Api.auth.SentCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.SentCode - } - return result - }) - } -} -public extension Api.functions.auth { - static func resetAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1616179942) - - return (FunctionDescription(name: "auth.resetAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.auth { - static func sendCode(phoneNumber: String, apiId: Int32, apiHash: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1502141361) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeInt32(apiId, buffer: buffer, boxed: false) - serializeString(apiHash, buffer: buffer, boxed: false) - settings.serialize(buffer, true) - return (FunctionDescription(name: "auth.sendCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in - let reader = BufferReader(buffer) - var result: Api.auth.SentCode? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.SentCode - } - return result - }) - } -} -public extension Api.functions.auth { - static func signIn(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1126886015) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - serializeString(phoneCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.signIn", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.auth { - static func signUp(phoneNumber: String, phoneCodeHash: String, firstName: String, lastName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2131827673) - serializeString(phoneNumber, buffer: buffer, boxed: false) - serializeString(phoneCodeHash, buffer: buffer, boxed: false) - serializeString(firstName, buffer: buffer, boxed: false) - serializeString(lastName, buffer: buffer, boxed: false) - return (FunctionDescription(name: "auth.signUp", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in - let reader = BufferReader(buffer) - var result: Api.auth.Authorization? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.auth.Authorization - } - return result - }) - } -} -public extension Api.functions.bots { - static func answerWebhookJSONQuery(queryId: Int64, data: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-434028723) - serializeInt64(queryId, buffer: buffer, boxed: false) - data.serialize(buffer, true) - return (FunctionDescription(name: "bots.answerWebhookJSONQuery", parameters: [("queryId", String(describing: queryId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.bots { - static func getBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.BotCommand]>) { - let buffer = Buffer() - buffer.appendInt32(-481554986) - scope.serialize(buffer, true) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "bots.getBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.BotCommand]? in - let reader = BufferReader(buffer) - var result: [Api.BotCommand]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self) - } - return result - }) - } -} -public extension Api.functions.bots { - static func getBotMenuButton(userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1671369944) - userId.serialize(buffer, true) - return (FunctionDescription(name: "bots.getBotMenuButton", parameters: [("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.BotMenuButton? in - let reader = BufferReader(buffer) - var result: Api.BotMenuButton? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.BotMenuButton - } - return result - }) - } -} -public extension Api.functions.bots { - static func resetBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1032708345) - scope.serialize(buffer, true) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "bots.resetBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.bots { - static func sendCustomRequest(customMethod: String, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1440257555) - serializeString(customMethod, buffer: buffer, boxed: false) - params.serialize(buffer, true) - return (FunctionDescription(name: "bots.sendCustomRequest", parameters: [("customMethod", String(describing: customMethod)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.DataJSON? in - let reader = BufferReader(buffer) - var result: Api.DataJSON? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.DataJSON - } - return result - }) - } -} -public extension Api.functions.bots { - static func setBotBroadcastDefaultAdminRights(adminRights: Api.ChatAdminRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2021942497) - adminRights.serialize(buffer, true) - return (FunctionDescription(name: "bots.setBotBroadcastDefaultAdminRights", parameters: [("adminRights", String(describing: adminRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.bots { - static func setBotCommands(scope: Api.BotCommandScope, langCode: String, commands: [Api.BotCommand]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(85399130) - scope.serialize(buffer, true) - serializeString(langCode, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(commands.count)) - for item in commands { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "bots.setBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode)), ("commands", String(describing: commands))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.bots { - static func setBotGroupDefaultAdminRights(adminRights: Api.ChatAdminRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1839281686) - adminRights.serialize(buffer, true) - return (FunctionDescription(name: "bots.setBotGroupDefaultAdminRights", parameters: [("adminRights", String(describing: adminRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.bots { - static func setBotMenuButton(userId: Api.InputUser, button: Api.BotMenuButton) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1157944655) - userId.serialize(buffer, true) - button.serialize(buffer, true) - return (FunctionDescription(name: "bots.setBotMenuButton", parameters: [("userId", String(describing: userId)), ("button", String(describing: button))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func checkUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(283557164) - channel.serialize(buffer, true) - serializeString(username, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.checkUsername", parameters: [("channel", String(describing: channel)), ("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func convertToGigagroup(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(187239529) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.convertToGigagroup", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func createChannel(flags: Int32, title: String, about: String, geoPoint: Api.InputGeoPoint?, address: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1029681423) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(about, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {geoPoint!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(address!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "channels.createChannel", parameters: [("flags", String(describing: flags)), ("title", String(describing: title)), ("about", String(describing: about)), ("geoPoint", String(describing: geoPoint)), ("address", String(describing: address))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func deleteChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1072619549) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.deleteChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func deleteHistory(flags: Int32, channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1683319225) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.deleteHistory", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func deleteMessages(channel: Api.InputChannel, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2067661490) - channel.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "channels.deleteMessages", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages - } - return result - }) - } -} -public extension Api.functions.channels { - static func deleteParticipantHistory(channel: Api.InputChannel, participant: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(913655003) - channel.serialize(buffer, true) - participant.serialize(buffer, true) - return (FunctionDescription(name: "channels.deleteParticipantHistory", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedHistory? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory - } - return result - }) - } -} -public extension Api.functions.channels { - static func editAdmin(channel: Api.InputChannel, userId: Api.InputUser, adminRights: Api.ChatAdminRights, rank: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-751007486) - channel.serialize(buffer, true) - userId.serialize(buffer, true) - adminRights.serialize(buffer, true) - serializeString(rank, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.editAdmin", parameters: [("channel", String(describing: channel)), ("userId", String(describing: userId)), ("adminRights", String(describing: adminRights)), ("rank", String(describing: rank))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func editBanned(channel: Api.InputChannel, participant: Api.InputPeer, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1763259007) - channel.serialize(buffer, true) - participant.serialize(buffer, true) - bannedRights.serialize(buffer, true) - return (FunctionDescription(name: "channels.editBanned", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant)), ("bannedRights", String(describing: bannedRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func editCreator(channel: Api.InputChannel, userId: Api.InputUser, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1892102881) - channel.serialize(buffer, true) - userId.serialize(buffer, true) - password.serialize(buffer, true) - return (FunctionDescription(name: "channels.editCreator", parameters: [("channel", String(describing: channel)), ("userId", String(describing: userId)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func editLocation(channel: Api.InputChannel, geoPoint: Api.InputGeoPoint, address: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1491484525) - channel.serialize(buffer, true) - geoPoint.serialize(buffer, true) - serializeString(address, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.editLocation", parameters: [("channel", String(describing: channel)), ("geoPoint", String(describing: geoPoint)), ("address", String(describing: address))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func editPhoto(channel: Api.InputChannel, photo: Api.InputChatPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-248621111) - channel.serialize(buffer, true) - photo.serialize(buffer, true) - return (FunctionDescription(name: "channels.editPhoto", parameters: [("channel", String(describing: channel)), ("photo", String(describing: photo))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func editTitle(channel: Api.InputChannel, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1450044624) - channel.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.editTitle", parameters: [("channel", String(describing: channel)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func exportMessageLink(flags: Int32, channel: Api.InputChannel, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-432034325) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.exportMessageLink", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedMessageLink? in - let reader = BufferReader(buffer) - var result: Api.ExportedMessageLink? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.ExportedMessageLink - } - return result - }) - } -} -public extension Api.functions.channels { - static func getAdminLog(flags: Int32, channel: Api.InputChannel, q: String, eventsFilter: Api.ChannelAdminLogEventsFilter?, admins: [Api.InputUser]?, maxId: Int64, minId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(870184064) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - serializeString(q, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {eventsFilter!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(admins!.count)) - for item in admins! { - item.serialize(buffer, true) - }} - serializeInt64(maxId, buffer: buffer, boxed: false) - serializeInt64(minId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.getAdminLog", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("q", String(describing: q)), ("eventsFilter", String(describing: eventsFilter)), ("admins", String(describing: admins)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.AdminLogResults? in - let reader = BufferReader(buffer) - var result: Api.channels.AdminLogResults? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.channels.AdminLogResults - } - return result - }) - } -} -public extension Api.functions.channels { - static func getAdminedPublicChannels(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-122669393) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.getAdminedPublicChannels", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.channels { - static func getChannels(id: [Api.InputChannel]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(176122811) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "channels.getChannels", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.channels { - static func getFullChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(141781513) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.getFullChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatFull? in - let reader = BufferReader(buffer) - var result: Api.messages.ChatFull? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ChatFull - } - return result - }) - } -} -public extension Api.functions.channels { - static func getGroupsForDiscussion() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-170208392) - - return (FunctionDescription(name: "channels.getGroupsForDiscussion", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.channels { - static func getInactiveChannels() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(300429806) - - return (FunctionDescription(name: "channels.getInactiveChannels", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.InactiveChats? in - let reader = BufferReader(buffer) - var result: Api.messages.InactiveChats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.InactiveChats - } - return result - }) - } -} -public extension Api.functions.channels { - static func getLeftChannels(offset: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2092831552) - serializeInt32(offset, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.getLeftChannels", parameters: [("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.channels { - static func getMessages(channel: Api.InputChannel, id: [Api.InputMessage]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1383294429) - channel.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "channels.getMessages", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.channels { - static func getParticipant(channel: Api.InputChannel, participant: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1599378234) - channel.serialize(buffer, true) - participant.serialize(buffer, true) - return (FunctionDescription(name: "channels.getParticipant", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipant? in - let reader = BufferReader(buffer) - var result: Api.channels.ChannelParticipant? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipant - } - return result - }) - } -} -public extension Api.functions.channels { - static func getParticipants(channel: Api.InputChannel, filter: Api.ChannelParticipantsFilter, offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2010044880) - channel.serialize(buffer, true) - filter.serialize(buffer, true) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.getParticipants", parameters: [("channel", String(describing: channel)), ("filter", String(describing: filter)), ("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipants? in - let reader = BufferReader(buffer) - var result: Api.channels.ChannelParticipants? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipants - } - return result - }) - } -} -public extension Api.functions.channels { - static func getSendAs(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(231174382) - peer.serialize(buffer, true) - return (FunctionDescription(name: "channels.getSendAs", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.SendAsPeers? in - let reader = BufferReader(buffer) - var result: Api.channels.SendAsPeers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.channels.SendAsPeers - } - return result - }) - } -} -public extension Api.functions.channels { - static func getSponsoredMessages(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-333377601) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.getSponsoredMessages", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SponsoredMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.SponsoredMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SponsoredMessages - } - return result - }) - } -} -public extension Api.functions.channels { - static func inviteToChannel(channel: Api.InputChannel, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(429865580) - channel.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { item.serialize(buffer, true) } - return (FunctionDescription(name: "channels.inviteToChannel", parameters: [("channel", String(describing: channel)), ("users", String(describing: users))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func joinChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(615851205) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.joinChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func leaveChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-130635115) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.leaveChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-871347913) - channel.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.readHistory", parameters: [("channel", String(describing: channel)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func readMessageContents(channel: Api.InputChannel, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-357180360) - channel.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) + break + case .photosSlice(let count, let photos, let users): + if boxed { + buffer.appendInt32(352657236) } - return (FunctionDescription(name: "channels.readMessageContents", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func reportSpam(channel: Api.InputChannel, participant: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-196443371) - channel.serialize(buffer, true) - participant.serialize(buffer, true) + serializeInt32(count, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "channels.reportSpam", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func setDiscussionGroup(broadcast: Api.InputChannel, group: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1079520178) - broadcast.serialize(buffer, true) - group.serialize(buffer, true) - return (FunctionDescription(name: "channels.setDiscussionGroup", parameters: [("broadcast", String(describing: broadcast)), ("group", String(describing: group))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func setStickers(channel: Api.InputChannel, stickerset: Api.InputStickerSet) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-359881479) - channel.serialize(buffer, true) - stickerset.serialize(buffer, true) - return (FunctionDescription(name: "channels.setStickers", parameters: [("channel", String(describing: channel)), ("stickerset", String(describing: stickerset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func toggleJoinRequest(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1277789622) - channel.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "channels.toggleJoinRequest", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func toggleJoinToSend(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-456419968) - channel.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "channels.toggleJoinToSend", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func togglePreHistoryHidden(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-356796084) - channel.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "channels.togglePreHistoryHidden", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func toggleSignatures(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(527021574) - channel.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "channels.toggleSignatures", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func toggleSlowMode(channel: Api.InputChannel, seconds: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-304832784) - channel.serialize(buffer, true) - serializeInt32(seconds, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.toggleSlowMode", parameters: [("channel", String(describing: channel)), ("seconds", String(describing: seconds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func updateUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(890549214) - channel.serialize(buffer, true) - serializeString(username, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.updateUsername", parameters: [("channel", String(describing: channel)), ("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.channels { - static func viewSponsoredMessage(channel: Api.InputChannel, randomId: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1095836780) - channel.serialize(buffer, true) - serializeBytes(randomId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.viewSponsoredMessage", parameters: [("channel", String(describing: channel)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func acceptContact(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-130964977) - id.serialize(buffer, true) - return (FunctionDescription(name: "contacts.acceptContact", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.contacts { - static func addContact(flags: Int32, id: Api.InputUser, firstName: String, lastName: String, phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-386636848) - serializeInt32(flags, buffer: buffer, boxed: false) - id.serialize(buffer, true) - serializeString(firstName, buffer: buffer, boxed: false) - serializeString(lastName, buffer: buffer, boxed: false) - serializeString(phone, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.addContact", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("phone", String(describing: phone))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.contacts { - static func block(id: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1758204945) - id.serialize(buffer, true) - return (FunctionDescription(name: "contacts.block", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func blockFromReplies(flags: Int32, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(698914348) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.blockFromReplies", parameters: [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.contacts { - static func deleteByPhones(phones: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(269745566) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(phones.count)) - for item in phones { - serializeString(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "contacts.deleteByPhones", parameters: [("phones", String(describing: phones))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func deleteContacts(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(157945344) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { + buffer.appendInt32(Int32(photos.count)) + for item in photos { item.serialize(buffer, true) } - return (FunctionDescription(name: "contacts.deleteContacts", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getBlocked(offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-176409329) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.getBlocked", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Blocked? in - let reader = BufferReader(buffer) - var result: Api.contacts.Blocked? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.Blocked - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getContactIDs(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) { - let buffer = Buffer() - buffer.appendInt32(2061264541) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.getContactIDs", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in - let reader = BufferReader(buffer) - var result: [Int32]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getContacts(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1574346258) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.getContacts", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Contacts? in - let reader = BufferReader(buffer) - var result: Api.contacts.Contacts? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.Contacts - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getLocated(flags: Int32, geoPoint: Api.InputGeoPoint, selfExpires: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-750207932) - serializeInt32(flags, buffer: buffer, boxed: false) - geoPoint.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(selfExpires!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "contacts.getLocated", parameters: [("flags", String(describing: flags)), ("geoPoint", String(describing: geoPoint)), ("selfExpires", String(describing: selfExpires))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getSaved() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SavedContact]>) { - let buffer = Buffer() - buffer.appendInt32(-2098076769) - - return (FunctionDescription(name: "contacts.getSaved", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SavedContact]? in - let reader = BufferReader(buffer) - var result: [Api.SavedContact]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SavedContact.self) - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getStatuses() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ContactStatus]>) { - let buffer = Buffer() - buffer.appendInt32(-995929106) - - return (FunctionDescription(name: "contacts.getStatuses", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.ContactStatus]? in - let reader = BufferReader(buffer) - var result: [Api.ContactStatus]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.ContactStatus.self) - } - return result - }) - } -} -public extension Api.functions.contacts { - static func getTopPeers(flags: Int32, offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1758168906) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.getTopPeers", parameters: [("flags", String(describing: flags)), ("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.TopPeers? in - let reader = BufferReader(buffer) - var result: Api.contacts.TopPeers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.TopPeers - } - return result - }) - } -} -public extension Api.functions.contacts { - static func importContacts(contacts: [Api.InputContact]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(746589157) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(contacts.count)) - for item in contacts { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "contacts.importContacts", parameters: [("contacts", String(describing: contacts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ImportedContacts? in - let reader = BufferReader(buffer) - var result: Api.contacts.ImportedContacts? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.ImportedContacts - } - return result - }) - } -} -public extension Api.functions.contacts { - static func resetSaved() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2020263951) - - return (FunctionDescription(name: "contacts.resetSaved", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func resetTopPeerRating(category: Api.TopPeerCategory, peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(451113900) - category.serialize(buffer, true) - peer.serialize(buffer, true) - return (FunctionDescription(name: "contacts.resetTopPeerRating", parameters: [("category", String(describing: category)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func resolvePhone(phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1963375804) - serializeString(phone, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.resolvePhone", parameters: [("phone", String(describing: phone))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ResolvedPeer? in - let reader = BufferReader(buffer) - var result: Api.contacts.ResolvedPeer? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.ResolvedPeer - } - return result - }) - } -} -public extension Api.functions.contacts { - static func resolveUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-113456221) - serializeString(username, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.resolveUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ResolvedPeer? in - let reader = BufferReader(buffer) - var result: Api.contacts.ResolvedPeer? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.ResolvedPeer - } - return result - }) - } -} -public extension Api.functions.contacts { - static func search(q: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(301470424) - serializeString(q, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "contacts.search", parameters: [("q", String(describing: q)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Found? in - let reader = BufferReader(buffer) - var result: Api.contacts.Found? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.contacts.Found - } - return result - }) - } -} -public extension Api.functions.contacts { - static func toggleTopPeers(enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2062238246) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "contacts.toggleTopPeers", parameters: [("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.contacts { - static func unblock(id: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1096393392) - id.serialize(buffer, true) - return (FunctionDescription(name: "contacts.unblock", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.folders { - static func deleteFolder(folderId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(472471681) - serializeInt32(folderId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "folders.deleteFolder", parameters: [("folderId", String(describing: folderId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.folders { - static func editPeerFolders(folderPeers: [Api.InputFolderPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1749536939) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(folderPeers.count)) - for item in folderPeers { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "folders.editPeerFolders", parameters: [("folderPeers", String(describing: folderPeers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.help { - static func acceptTermsOfService(id: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-294455398) - id.serialize(buffer, true) - return (FunctionDescription(name: "help.acceptTermsOfService", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.help { - static func dismissSuggestion(peer: Api.InputPeer, suggestion: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-183649631) - peer.serialize(buffer, true) - serializeString(suggestion, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.dismissSuggestion", parameters: [("peer", String(describing: peer)), ("suggestion", String(describing: suggestion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.help { - static func editUserInfo(userId: Api.InputUser, message: String, entities: [Api.MessageEntity]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1723407216) - userId.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities.count)) - for item in entities { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "help.editUserInfo", parameters: [("userId", String(describing: userId)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.UserInfo? in - let reader = BufferReader(buffer) - var result: Api.help.UserInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.UserInfo - } - return result - }) - } -} -public extension Api.functions.help { - static func getAppChangelog(prevAppVersion: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1877938321) - serializeString(prevAppVersion, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getAppChangelog", parameters: [("prevAppVersion", String(describing: prevAppVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.help { - static func getAppConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1735311088) - - return (FunctionDescription(name: "help.getAppConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.JSONValue? in - let reader = BufferReader(buffer) - var result: Api.JSONValue? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.JSONValue - } - return result - }) - } -} -public extension Api.functions.help { - static func getAppUpdate(source: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1378703997) - serializeString(source, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getAppUpdate", parameters: [("source", String(describing: source))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.AppUpdate? in - let reader = BufferReader(buffer) - var result: Api.help.AppUpdate? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.AppUpdate - } - return result - }) - } -} -public extension Api.functions.help { - static func getCdnConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1375900482) - - return (FunctionDescription(name: "help.getCdnConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.CdnConfig? in - let reader = BufferReader(buffer) - var result: Api.CdnConfig? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.CdnConfig - } - return result - }) - } -} -public extension Api.functions.help { - static func getConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-990308245) - - return (FunctionDescription(name: "help.getConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Config? in - let reader = BufferReader(buffer) - var result: Api.Config? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Config - } - return result - }) - } -} -public extension Api.functions.help { - static func getCountriesList(langCode: String, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1935116200) - serializeString(langCode, buffer: buffer, boxed: false) - serializeInt32(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getCountriesList", parameters: [("langCode", String(describing: langCode)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.CountriesList? in - let reader = BufferReader(buffer) - var result: Api.help.CountriesList? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.CountriesList - } - return result - }) - } -} -public extension Api.functions.help { - static func getDeepLinkInfo(path: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1072547679) - serializeString(path, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getDeepLinkInfo", parameters: [("path", String(describing: path))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.DeepLinkInfo? in - let reader = BufferReader(buffer) - var result: Api.help.DeepLinkInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.DeepLinkInfo - } - return result - }) - } -} -public extension Api.functions.help { - static func getInviteText() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1295590211) - - return (FunctionDescription(name: "help.getInviteText", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.InviteText? in - let reader = BufferReader(buffer) - var result: Api.help.InviteText? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.InviteText - } - return result - }) - } -} -public extension Api.functions.help { - static func getNearestDc() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(531836966) - - return (FunctionDescription(name: "help.getNearestDc", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.NearestDc? in - let reader = BufferReader(buffer) - var result: Api.NearestDc? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.NearestDc - } - return result - }) - } -} -public extension Api.functions.help { - static func getPassportConfig(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-966677240) - serializeInt32(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getPassportConfig", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PassportConfig? in - let reader = BufferReader(buffer) - var result: Api.help.PassportConfig? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.PassportConfig - } - return result - }) - } -} -public extension Api.functions.help { - static func getPremiumPromo() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1206152236) - - return (FunctionDescription(name: "help.getPremiumPromo", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PremiumPromo? in - let reader = BufferReader(buffer) - var result: Api.help.PremiumPromo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.PremiumPromo - } - return result - }) - } -} -public extension Api.functions.help { - static func getPromoData() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1063816159) - - return (FunctionDescription(name: "help.getPromoData", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PromoData? in - let reader = BufferReader(buffer) - var result: Api.help.PromoData? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.PromoData - } - return result - }) - } -} -public extension Api.functions.help { - static func getRecentMeUrls(referer: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1036054804) - serializeString(referer, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.getRecentMeUrls", parameters: [("referer", String(describing: referer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.RecentMeUrls? in - let reader = BufferReader(buffer) - var result: Api.help.RecentMeUrls? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.RecentMeUrls - } - return result - }) - } -} -public extension Api.functions.help { - static func getSupport() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1663104819) - - return (FunctionDescription(name: "help.getSupport", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.Support? in - let reader = BufferReader(buffer) - var result: Api.help.Support? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.Support - } - return result - }) - } -} -public extension Api.functions.help { - static func getSupportName() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-748624084) - - return (FunctionDescription(name: "help.getSupportName", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.SupportName? in - let reader = BufferReader(buffer) - var result: Api.help.SupportName? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.SupportName - } - return result - }) - } -} -public extension Api.functions.help { - static func getTermsOfServiceUpdate() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(749019089) - - return (FunctionDescription(name: "help.getTermsOfServiceUpdate", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.TermsOfServiceUpdate? in - let reader = BufferReader(buffer) - var result: Api.help.TermsOfServiceUpdate? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.TermsOfServiceUpdate - } - return result - }) - } -} -public extension Api.functions.help { - static func getUserInfo(userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(59377875) - userId.serialize(buffer, true) - return (FunctionDescription(name: "help.getUserInfo", parameters: [("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.UserInfo? in - let reader = BufferReader(buffer) - var result: Api.help.UserInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.help.UserInfo - } - return result - }) - } -} -public extension Api.functions.help { - static func hidePromoData(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(505748629) - peer.serialize(buffer, true) - return (FunctionDescription(name: "help.hidePromoData", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.help { - static func saveAppLog(events: [Api.InputAppEvent]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1862465352) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(events.count)) - for item in events { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "help.saveAppLog", parameters: [("events", String(describing: events))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.help { - static func setBotUpdatesStatus(pendingUpdatesCount: Int32, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-333262899) - serializeInt32(pendingUpdatesCount, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - return (FunctionDescription(name: "help.setBotUpdatesStatus", parameters: [("pendingUpdatesCount", String(describing: pendingUpdatesCount)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.help { - static func test() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1058929929) - - return (FunctionDescription(name: "help.test", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.langpack { - static func getDifference(langPack: String, langCode: String, fromVersion: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-845657435) - serializeString(langPack, buffer: buffer, boxed: false) - serializeString(langCode, buffer: buffer, boxed: false) - serializeInt32(fromVersion, buffer: buffer, boxed: false) - return (FunctionDescription(name: "langpack.getDifference", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode)), ("fromVersion", String(describing: fromVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackDifference? in - let reader = BufferReader(buffer) - var result: Api.LangPackDifference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.LangPackDifference - } - return result - }) - } -} -public extension Api.functions.langpack { - static func getLangPack(langPack: String, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-219008246) - serializeString(langPack, buffer: buffer, boxed: false) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "langpack.getLangPack", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackDifference? in - let reader = BufferReader(buffer) - var result: Api.LangPackDifference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.LangPackDifference - } - return result - }) - } -} -public extension Api.functions.langpack { - static func getLanguage(langPack: String, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1784243458) - serializeString(langPack, buffer: buffer, boxed: false) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "langpack.getLanguage", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackLanguage? in - let reader = BufferReader(buffer) - var result: Api.LangPackLanguage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.LangPackLanguage - } - return result - }) - } -} -public extension Api.functions.langpack { - static func getLanguages(langPack: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.LangPackLanguage]>) { - let buffer = Buffer() - buffer.appendInt32(1120311183) - serializeString(langPack, buffer: buffer, boxed: false) - return (FunctionDescription(name: "langpack.getLanguages", parameters: [("langPack", String(describing: langPack))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.LangPackLanguage]? in - let reader = BufferReader(buffer) - var result: [Api.LangPackLanguage]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackLanguage.self) - } - return result - }) - } -} -public extension Api.functions.langpack { - static func getStrings(langPack: String, langCode: String, keys: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.LangPackString]>) { - let buffer = Buffer() - buffer.appendInt32(-269862909) - serializeString(langPack, buffer: buffer, boxed: false) - serializeString(langCode, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(keys.count)) - for item in keys { - serializeString(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "langpack.getStrings", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode)), ("keys", String(describing: keys))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.LangPackString]? in - let reader = BufferReader(buffer) - var result: [Api.LangPackString]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackString.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func acceptEncryption(peer: Api.InputEncryptedChat, gB: Buffer, keyFingerprint: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1035731989) - peer.serialize(buffer, true) - serializeBytes(gB, buffer: buffer, boxed: false) - serializeInt64(keyFingerprint, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.acceptEncryption", parameters: [("peer", String(describing: peer)), ("gB", String(describing: gB)), ("keyFingerprint", String(describing: keyFingerprint))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedChat? in - let reader = BufferReader(buffer) - var result: Api.EncryptedChat? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EncryptedChat - } - return result - }) - } -} -public extension Api.functions.messages { - static func acceptUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1322487515) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.acceptUrlAuth", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("buttonId", String(describing: buttonId)), ("url", String(describing: url))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in - let reader = BufferReader(buffer) - var result: Api.UrlAuthResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.UrlAuthResult - } - return result - }) - } -} -public extension Api.functions.messages { - static func addChatUser(chatId: Int64, userId: Api.InputUser, fwdLimit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-230206493) - serializeInt64(chatId, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - serializeInt32(fwdLimit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.addChatUser", parameters: [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("fwdLimit", String(describing: fwdLimit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func checkChatInvite(hash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1051570619) - serializeString(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.checkChatInvite", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ChatInvite? in - let reader = BufferReader(buffer) - var result: Api.ChatInvite? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.ChatInvite - } - return result - }) - } -} -public extension Api.functions.messages { - static func checkHistoryImport(importHead: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1140726259) - serializeString(importHead, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.checkHistoryImport", parameters: [("importHead", String(describing: importHead))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImportParsed? in - let reader = BufferReader(buffer) - var result: Api.messages.HistoryImportParsed? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImportParsed - } - return result - }) - } -} -public extension Api.functions.messages { - static func checkHistoryImportPeer(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1573261059) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.checkHistoryImportPeer", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.CheckedHistoryImportPeer? in - let reader = BufferReader(buffer) - var result: Api.messages.CheckedHistoryImportPeer? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.CheckedHistoryImportPeer - } - return result - }) - } -} -public extension Api.functions.messages { - static func clearAllDrafts() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2119757468) - - return (FunctionDescription(name: "messages.clearAllDrafts", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func clearRecentStickers(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1986437075) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.clearRecentStickers", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func createChat(users: [Api.InputUser], title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(164303470) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { item.serialize(buffer, true) } - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.createChat", parameters: [("users", String(describing: users)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .photos(let photos, let users): + return ("photos", [("photos", String(describing: photos)), ("users", String(describing: users))]) + case .photosSlice(let count, let photos, let users): + return ("photosSlice", [("count", String(describing: count)), ("photos", String(describing: photos)), ("users", String(describing: users))]) + } + } + + public static func parse_photos(_ reader: BufferReader) -> Photos? { + var _1: [Api.Photo]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.photos.Photos.photos(photos: _1!, users: _2!) + } + else { + return nil + } + } + public static func parse_photosSlice(_ reader: BufferReader) -> Photos? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.Photo]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Photo.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.photos.Photos.photosSlice(count: _1!, photos: _2!, users: _3!) + } + else { + return nil + } + } + + } } -public extension Api.functions.messages { - static func deleteChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1540419152) - serializeInt64(chatId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.deleteChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteChatUser(flags: Int32, chatId: Int64, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1575461717) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(chatId, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - return (FunctionDescription(name: "messages.deleteChatUser", parameters: [("flags", String(describing: flags)), ("chatId", String(describing: chatId)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-731601877) - peer.serialize(buffer, true) - serializeString(link, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.deleteExportedChatInvite", parameters: [("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteHistory(flags: Int32, peer: Api.InputPeer, maxId: Int32, minDate: Int32?, maxDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1332768214) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(minDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(maxDate!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.deleteHistory", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedHistory? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteMessages(flags: Int32, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-443640366) - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) +public extension Api.stats { + enum BroadcastStats: TypeConstructorDescription { + case broadcastStats(period: Api.StatsDateRangeDays, followers: Api.StatsAbsValueAndPrev, viewsPerPost: Api.StatsAbsValueAndPrev, sharesPerPost: Api.StatsAbsValueAndPrev, enabledNotifications: Api.StatsPercentValue, growthGraph: Api.StatsGraph, followersGraph: Api.StatsGraph, muteGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, interactionsGraph: Api.StatsGraph, ivInteractionsGraph: Api.StatsGraph, viewsBySourceGraph: Api.StatsGraph, newFollowersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, recentMessageInteractions: [Api.MessageInteractionCounters]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions): + if boxed { + buffer.appendInt32(-1107852396) } - return (FunctionDescription(name: "messages.deleteMessages", parameters: [("flags", String(describing: flags)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages - } - return result - }) - } -} -public extension Api.functions.messages { - static func deletePhoneCallHistory(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-104078327) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.deletePhoneCallHistory", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedFoundMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedFoundMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedFoundMessages - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteRevokedExportedChatInvites(peer: Api.InputPeer, adminId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1452833749) - peer.serialize(buffer, true) - adminId.serialize(buffer, true) - return (FunctionDescription(name: "messages.deleteRevokedExportedChatInvites", parameters: [("peer", String(describing: peer)), ("adminId", String(describing: adminId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func deleteScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1504586518) - peer.serialize(buffer, true) + period.serialize(buffer, true) + followers.serialize(buffer, true) + viewsPerPost.serialize(buffer, true) + sharesPerPost.serialize(buffer, true) + enabledNotifications.serialize(buffer, true) + growthGraph.serialize(buffer, true) + followersGraph.serialize(buffer, true) + muteGraph.serialize(buffer, true) + topHoursGraph.serialize(buffer, true) + interactionsGraph.serialize(buffer, true) + ivInteractionsGraph.serialize(buffer, true) + viewsBySourceGraph.serialize(buffer, true) + newFollowersBySourceGraph.serialize(buffer, true) + languagesGraph.serialize(buffer, true) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.deleteScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func discardEncryption(flags: Int32, chatId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-208425312) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(chatId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.discardEncryption", parameters: [("flags", String(describing: flags)), ("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func editChatAbout(peer: Api.InputPeer, about: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-554301545) - peer.serialize(buffer, true) - serializeString(about, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.editChatAbout", parameters: [("peer", String(describing: peer)), ("about", String(describing: about))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func editChatAdmin(chatId: Int64, userId: Api.InputUser, isAdmin: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1470377534) - serializeInt64(chatId, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - isAdmin.serialize(buffer, true) - return (FunctionDescription(name: "messages.editChatAdmin", parameters: [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("isAdmin", String(describing: isAdmin))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func editChatDefaultBannedRights(peer: Api.InputPeer, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1517917375) - peer.serialize(buffer, true) - bannedRights.serialize(buffer, true) - return (FunctionDescription(name: "messages.editChatDefaultBannedRights", parameters: [("peer", String(describing: peer)), ("bannedRights", String(describing: bannedRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func editChatPhoto(chatId: Int64, photo: Api.InputChatPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(903730804) - serializeInt64(chatId, buffer: buffer, boxed: false) - photo.serialize(buffer, true) - return (FunctionDescription(name: "messages.editChatPhoto", parameters: [("chatId", String(describing: chatId)), ("photo", String(describing: photo))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func editChatTitle(chatId: Int64, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1937260541) - serializeInt64(chatId, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.editChatTitle", parameters: [("chatId", String(describing: chatId)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func editExportedChatInvite(flags: Int32, peer: Api.InputPeer, link: String, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Api.Bool?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1110823051) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeString(link, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {requestNeeded!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.editExportedChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("requestNeeded", String(describing: requestNeeded)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in - let reader = BufferReader(buffer) - var result: Api.messages.ExportedChatInvite? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite - } - return result - }) - } -} -public extension Api.functions.messages { - static func editInlineBotMessage(flags: Int32, id: Api.InputBotInlineMessageID, message: String?, media: Api.InputMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2091549254) - serializeInt32(flags, buffer: buffer, boxed: false) - id.serialize(buffer, true) - if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "messages.editInlineBotMessage", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func editMessage(flags: Int32, peer: Api.InputPeer, id: Int32, message: String?, media: Api.InputMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1224152952) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 15) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.editMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1607670315) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in - let reader = BufferReader(buffer) - var result: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - return result - }) - } -} -public extension Api.functions.messages { - static func faveSticker(id: Api.InputDocument, unfave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1174420133) - id.serialize(buffer, true) - unfave.serialize(buffer, true) - return (FunctionDescription(name: "messages.faveSticker", parameters: [("id", String(describing: id)), ("unfave", String(describing: unfave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-869258997) - serializeInt32(flags, buffer: buffer, boxed: false) - fromPeer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(randomId.count)) - for item in randomId { - serializeInt64(item, buffer: buffer, boxed: false) - } - toPeer.serialize(buffer, true) - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAdminsWithInvites(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(958457583) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.getAdminsWithInvites", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatAdminsWithInvites? in - let reader = BufferReader(buffer) - var result: Api.messages.ChatAdminsWithInvites? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ChatAdminsWithInvites - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAllChats(exceptIds: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2023787330) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(exceptIds.count)) - for item in exceptIds { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.getAllChats", parameters: [("exceptIds", String(describing: exceptIds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAllDrafts() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1782549861) - - return (FunctionDescription(name: "messages.getAllDrafts", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAllStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1197432408) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getAllStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AllStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.AllStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AllStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getArchivedStickers(flags: Int32, offsetId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1475442322) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getArchivedStickers", parameters: [("flags", String(describing: flags)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ArchivedStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.ArchivedStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ArchivedStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAttachMenuBot(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1998676370) - bot.serialize(buffer, true) - return (FunctionDescription(name: "messages.getAttachMenuBot", parameters: [("bot", String(describing: bot))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AttachMenuBotsBot? in - let reader = BufferReader(buffer) - var result: Api.AttachMenuBotsBot? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.AttachMenuBotsBot - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAttachMenuBots(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(385663691) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getAttachMenuBots", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AttachMenuBots? in - let reader = BufferReader(buffer) - var result: Api.AttachMenuBots? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.AttachMenuBots - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAttachedStickers(media: Api.InputStickeredMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StickerSetCovered]>) { - let buffer = Buffer() - buffer.appendInt32(-866424884) - media.serialize(buffer, true) - return (FunctionDescription(name: "messages.getAttachedStickers", parameters: [("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.StickerSetCovered]? in - let reader = BufferReader(buffer) - var result: [Api.StickerSetCovered]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getAvailableReactions(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(417243308) - serializeInt32(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getAvailableReactions", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AvailableReactions? in - let reader = BufferReader(buffer) - var result: Api.messages.AvailableReactions? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AvailableReactions - } - return result - }) - } -} -public extension Api.functions.messages { - static func getBotCallbackAnswer(flags: Int32, peer: Api.InputPeer, msgId: Int32, data: Buffer?, password: Api.InputCheckPasswordSRP?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1824339449) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {password!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.getBotCallbackAnswer", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("data", String(describing: data)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.BotCallbackAnswer? in - let reader = BufferReader(buffer) - var result: Api.messages.BotCallbackAnswer? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.BotCallbackAnswer - } - return result - }) - } -} -public extension Api.functions.messages { - static func getChatInviteImporters(flags: Int32, peer: Api.InputPeer, link: String?, q: String?, offsetDate: Int32, offsetUser: Api.InputUser, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-553329330) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(q!, buffer: buffer, boxed: false)} - serializeInt32(offsetDate, buffer: buffer, boxed: false) - offsetUser.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getChatInviteImporters", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link)), ("q", String(describing: q)), ("offsetDate", String(describing: offsetDate)), ("offsetUser", String(describing: offsetUser)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatInviteImporters? in - let reader = BufferReader(buffer) - var result: Api.messages.ChatInviteImporters? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ChatInviteImporters - } - return result - }) - } -} -public extension Api.functions.messages { - static func getChats(id: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1240027791) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.getChats", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.messages { - static func getCommonChats(userId: Api.InputUser, maxId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-468934396) - userId.serialize(buffer, true) - serializeInt64(maxId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getCommonChats", parameters: [("userId", String(describing: userId)), ("maxId", String(describing: maxId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in - let reader = BufferReader(buffer) - var result: Api.messages.Chats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Chats - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDhConfig(version: Int32, randomLength: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(651135312) - serializeInt32(version, buffer: buffer, boxed: false) - serializeInt32(randomLength, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getDhConfig", parameters: [("version", String(describing: version)), ("randomLength", String(describing: randomLength))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.DhConfig? in - let reader = BufferReader(buffer) - var result: Api.messages.DhConfig? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.DhConfig - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDialogFilters() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogFilter]>) { - let buffer = Buffer() - buffer.appendInt32(-241247891) - - return (FunctionDescription(name: "messages.getDialogFilters", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogFilter]? in - let reader = BufferReader(buffer) - var result: [Api.DialogFilter]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilter.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDialogUnreadMarks() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogPeer]>) { - let buffer = Buffer() - buffer.appendInt32(585256482) - - return (FunctionDescription(name: "messages.getDialogUnreadMarks", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogPeer]? in - let reader = BufferReader(buffer) - var result: [Api.DialogPeer]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogPeer.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDialogs(flags: Int32, folderId: Int32?, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1594569905) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - serializeInt32(offsetDate, buffer: buffer, boxed: false) - serializeInt32(offsetId, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getDialogs", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("offsetDate", String(describing: offsetDate)), ("offsetId", String(describing: offsetId)), ("offsetPeer", String(describing: offsetPeer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Dialogs? in - let reader = BufferReader(buffer) - var result: Api.messages.Dialogs? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Dialogs - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDiscussionMessage(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1147761405) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getDiscussionMessage", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.DiscussionMessage? in - let reader = BufferReader(buffer) - var result: Api.messages.DiscussionMessage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.DiscussionMessage - } - return result - }) - } -} -public extension Api.functions.messages { - static func getDocumentByHash(sha256: Buffer, size: Int64, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1309538785) - serializeBytes(sha256, buffer: buffer, boxed: false) - serializeInt64(size, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getDocumentByHash", parameters: [("sha256", String(describing: sha256)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in - let reader = BufferReader(buffer) - var result: Api.Document? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Document - } - return result - }) - } -} -public extension Api.functions.messages { - static func getEmojiKeywords(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(899735650) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getEmojiKeywords", parameters: [("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiKeywordsDifference? in - let reader = BufferReader(buffer) - var result: Api.EmojiKeywordsDifference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EmojiKeywordsDifference - } - return result - }) - } -} -public extension Api.functions.messages { - static func getEmojiKeywordsDifference(langCode: String, fromVersion: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(352892591) - serializeString(langCode, buffer: buffer, boxed: false) - serializeInt32(fromVersion, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getEmojiKeywordsDifference", parameters: [("langCode", String(describing: langCode)), ("fromVersion", String(describing: fromVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiKeywordsDifference? in - let reader = BufferReader(buffer) - var result: Api.EmojiKeywordsDifference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EmojiKeywordsDifference - } - return result - }) - } -} -public extension Api.functions.messages { - static func getEmojiKeywordsLanguages(langCodes: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.EmojiLanguage]>) { - let buffer = Buffer() - buffer.appendInt32(1318675378) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(langCodes.count)) - for item in langCodes { - serializeString(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.getEmojiKeywordsLanguages", parameters: [("langCodes", String(describing: langCodes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.EmojiLanguage]? in - let reader = BufferReader(buffer) - var result: [Api.EmojiLanguage]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.EmojiLanguage.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getEmojiURL(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-709817306) - serializeString(langCode, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getEmojiURL", parameters: [("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiURL? in - let reader = BufferReader(buffer) - var result: Api.EmojiURL? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EmojiURL - } - return result - }) - } -} -public extension Api.functions.messages { - static func getExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1937010524) - peer.serialize(buffer, true) - serializeString(link, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getExportedChatInvite", parameters: [("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in - let reader = BufferReader(buffer) - var result: Api.messages.ExportedChatInvite? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite - } - return result - }) - } -} -public extension Api.functions.messages { - static func getExportedChatInvites(flags: Int32, peer: Api.InputPeer, adminId: Api.InputUser, offsetDate: Int32?, offsetLink: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1565154314) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - adminId.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(offsetLink!, buffer: buffer, boxed: false)} - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getExportedChatInvites", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("adminId", String(describing: adminId)), ("offsetDate", String(describing: offsetDate)), ("offsetLink", String(describing: offsetLink)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvites? in - let reader = BufferReader(buffer) - var result: Api.messages.ExportedChatInvites? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvites - } - return result - }) - } -} -public extension Api.functions.messages { - static func getFavedStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(82946729) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getFavedStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FavedStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.FavedStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.FavedStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getFeaturedStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1685588756) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getFeaturedStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.FeaturedStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getFullChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1364194508) - serializeInt64(chatId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getFullChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatFull? in - let reader = BufferReader(buffer) - var result: Api.messages.ChatFull? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.ChatFull - } - return result - }) - } -} -public extension Api.functions.messages { - static func getGameHighScores(peer: Api.InputPeer, id: Int32, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-400399203) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - return (FunctionDescription(name: "messages.getGameHighScores", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HighScores? in - let reader = BufferReader(buffer) - var result: Api.messages.HighScores? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.HighScores - } - return result - }) - } -} -public extension Api.functions.messages { - static func getHistory(peer: Api.InputPeer, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1143203525) - peer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(offsetDate, buffer: buffer, boxed: false) - serializeInt32(addOffset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(minId, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getHistory", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getInlineBotResults(flags: Int32, bot: Api.InputUser, peer: Api.InputPeer, geoPoint: Api.InputGeoPoint?, query: String, offset: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1364105629) - serializeInt32(flags, buffer: buffer, boxed: false) - bot.serialize(buffer, true) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {geoPoint!.serialize(buffer, true)} - serializeString(query, buffer: buffer, boxed: false) - serializeString(offset, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getInlineBotResults", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("peer", String(describing: peer)), ("geoPoint", String(describing: geoPoint)), ("query", String(describing: query)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.BotResults? in - let reader = BufferReader(buffer) - var result: Api.messages.BotResults? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.BotResults - } - return result - }) - } -} -public extension Api.functions.messages { - static func getInlineGameHighScores(id: Api.InputBotInlineMessageID, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(258170395) - id.serialize(buffer, true) - userId.serialize(buffer, true) - return (FunctionDescription(name: "messages.getInlineGameHighScores", parameters: [("id", String(describing: id)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HighScores? in - let reader = BufferReader(buffer) - var result: Api.messages.HighScores? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.HighScores - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMaskStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1678738104) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getMaskStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AllStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.AllStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AllStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMessageEditData(peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-39416522) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getMessageEditData", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageEditData? in - let reader = BufferReader(buffer) - var result: Api.messages.MessageEditData? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.MessageEditData - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMessageReactionsList(flags: Int32, peer: Api.InputPeer, id: Int32, reaction: String?, offset: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-521245833) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(offset!, buffer: buffer, boxed: false)} - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getMessageReactionsList", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("reaction", String(describing: reaction)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageReactionsList? in - let reader = BufferReader(buffer) - var result: Api.messages.MessageReactionsList? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.MessageReactionsList - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMessageReadParticipants(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { - let buffer = Buffer() - buffer.appendInt32(745510839) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getMessageReadParticipants", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in - let reader = BufferReader(buffer) - var result: [Int64]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMessages(id: [Api.InputMessage]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1673946374) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { + buffer.appendInt32(Int32(recentMessageInteractions.count)) + for item in recentMessageInteractions { item.serialize(buffer, true) } - return (FunctionDescription(name: "messages.getMessages", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .broadcastStats(let period, let followers, let viewsPerPost, let sharesPerPost, let enabledNotifications, let growthGraph, let followersGraph, let muteGraph, let topHoursGraph, let interactionsGraph, let ivInteractionsGraph, let viewsBySourceGraph, let newFollowersBySourceGraph, let languagesGraph, let recentMessageInteractions): + return ("broadcastStats", [("period", String(describing: period)), ("followers", String(describing: followers)), ("viewsPerPost", String(describing: viewsPerPost)), ("sharesPerPost", String(describing: sharesPerPost)), ("enabledNotifications", String(describing: enabledNotifications)), ("growthGraph", String(describing: growthGraph)), ("followersGraph", String(describing: followersGraph)), ("muteGraph", String(describing: muteGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("interactionsGraph", String(describing: interactionsGraph)), ("ivInteractionsGraph", String(describing: ivInteractionsGraph)), ("viewsBySourceGraph", String(describing: viewsBySourceGraph)), ("newFollowersBySourceGraph", String(describing: newFollowersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("recentMessageInteractions", String(describing: recentMessageInteractions))]) + } + } + + public static func parse_broadcastStats(_ reader: BufferReader) -> BroadcastStats? { + var _1: Api.StatsDateRangeDays? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays + } + var _2: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _3: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _4: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _5: Api.StatsPercentValue? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.StatsPercentValue + } + var _6: Api.StatsGraph? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _7: Api.StatsGraph? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _8: Api.StatsGraph? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _9: Api.StatsGraph? + if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _10: Api.StatsGraph? + if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _11: Api.StatsGraph? + if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _12: Api.StatsGraph? + if let signature = reader.readInt32() { + _12 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _13: Api.StatsGraph? + if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _14: Api.StatsGraph? + if let signature = reader.readInt32() { + _14 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _15: [Api.MessageInteractionCounters]? + if let _ = reader.readInt32() { + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageInteractionCounters.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = _10 != nil + let _c11 = _11 != nil + let _c12 = _12 != nil + let _c13 = _13 != nil + let _c14 = _14 != nil + let _c15 = _15 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { + return Api.stats.BroadcastStats.broadcastStats(period: _1!, followers: _2!, viewsPerPost: _3!, sharesPerPost: _4!, enabledNotifications: _5!, growthGraph: _6!, followersGraph: _7!, muteGraph: _8!, topHoursGraph: _9!, interactionsGraph: _10!, ivInteractionsGraph: _11!, viewsBySourceGraph: _12!, newFollowersBySourceGraph: _13!, languagesGraph: _14!, recentMessageInteractions: _15!) + } + else { + return nil + } + } + + } } -public extension Api.functions.messages { - static func getMessagesReactions(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1950707482) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) +public extension Api.stats { + enum MegagroupStats: TypeConstructorDescription { + case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users): + if boxed { + buffer.appendInt32(-276825834) } - return (FunctionDescription(name: "messages.getMessagesReactions", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func getMessagesViews(peer: Api.InputPeer, id: [Int32], increment: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1468322785) - peer.serialize(buffer, true) + period.serialize(buffer, true) + members.serialize(buffer, true) + messages.serialize(buffer, true) + viewers.serialize(buffer, true) + posters.serialize(buffer, true) + growthGraph.serialize(buffer, true) + membersGraph.serialize(buffer, true) + newMembersBySourceGraph.serialize(buffer, true) + languagesGraph.serialize(buffer, true) + messagesGraph.serialize(buffer, true) + actionsGraph.serialize(buffer, true) + topHoursGraph.serialize(buffer, true) + weekdaysGraph.serialize(buffer, true) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - increment.serialize(buffer, true) - return (FunctionDescription(name: "messages.getMessagesViews", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("increment", String(describing: increment))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageViews? in - let reader = BufferReader(buffer) - var result: Api.messages.MessageViews? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.MessageViews - } - return result - }) - } -} -public extension Api.functions.messages { - static func getOldFeaturedStickers(offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2127598753) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getOldFeaturedStickers", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.FeaturedStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getOnlines(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1848369232) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.getOnlines", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ChatOnlines? in - let reader = BufferReader(buffer) - var result: Api.ChatOnlines? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.ChatOnlines - } - return result - }) - } -} -public extension Api.functions.messages { - static func getPeerDialogs(peers: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-462373635) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "messages.getPeerDialogs", parameters: [("peers", String(describing: peers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerDialogs? in - let reader = BufferReader(buffer) - var result: Api.messages.PeerDialogs? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.PeerDialogs - } - return result - }) - } -} -public extension Api.functions.messages { - static func getPeerSettings(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-270948702) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.getPeerSettings", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerSettings? in - let reader = BufferReader(buffer) - var result: Api.messages.PeerSettings? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.PeerSettings - } - return result - }) - } -} -public extension Api.functions.messages { - static func getPinnedDialogs(folderId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-692498958) - serializeInt32(folderId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getPinnedDialogs", parameters: [("folderId", String(describing: folderId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerDialogs? in - let reader = BufferReader(buffer) - var result: Api.messages.PeerDialogs? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.PeerDialogs - } - return result - }) - } -} -public extension Api.functions.messages { - static func getPollResults(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1941660731) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getPollResults", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func getPollVotes(flags: Int32, peer: Api.InputPeer, id: Int32, option: Buffer?, offset: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1200736242) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeBytes(option!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(offset!, buffer: buffer, boxed: false)} - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getPollVotes", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("option", String(describing: option)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.VotesList? in - let reader = BufferReader(buffer) - var result: Api.messages.VotesList? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.VotesList - } - return result - }) - } -} -public extension Api.functions.messages { - static func getRecentLocations(peer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1881817312) - peer.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getRecentLocations", parameters: [("peer", String(describing: peer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getRecentStickers(flags: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1649852357) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getRecentStickers", parameters: [("flags", String(describing: flags)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.RecentStickers? in - let reader = BufferReader(buffer) - var result: Api.messages.RecentStickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.RecentStickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getReplies(peer: Api.InputPeer, msgId: Int32, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(584962828) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(offsetDate, buffer: buffer, boxed: false) - serializeInt32(addOffset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(minId, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getReplies", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSavedGifs(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1559270965) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getSavedGifs", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedGifs? in - let reader = BufferReader(buffer) - var result: Api.messages.SavedGifs? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SavedGifs - } - return result - }) - } -} -public extension Api.functions.messages { - static func getScheduledHistory(peer: Api.InputPeer, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-183077365) - peer.serialize(buffer, true) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getScheduledHistory", parameters: [("peer", String(describing: peer)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1111817116) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.getScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSearchCounters(peer: Api.InputPeer, filters: [Api.MessagesFilter]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.messages.SearchCounter]>) { - let buffer = Buffer() - buffer.appendInt32(1932455680) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(filters.count)) - for item in filters { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "messages.getSearchCounters", parameters: [("peer", String(describing: peer)), ("filters", String(describing: filters))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.messages.SearchCounter]? in - let reader = BufferReader(buffer) - var result: [Api.messages.SearchCounter]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.messages.SearchCounter.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSearchResultsCalendar(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, offsetDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1240514025) - peer.serialize(buffer, true) - filter.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(offsetDate, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getSearchResultsCalendar", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsCalendar? in - let reader = BufferReader(buffer) - var result: Api.messages.SearchResultsCalendar? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SearchResultsCalendar - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSearchResultsPositions(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1855292323) - peer.serialize(buffer, true) - filter.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getSearchResultsPositions", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsPositions? in - let reader = BufferReader(buffer) - var result: Api.messages.SearchResultsPositions? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SearchResultsPositions - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSplitRanges() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.MessageRange]>) { - let buffer = Buffer() - buffer.appendInt32(486505992) - - return (FunctionDescription(name: "messages.getSplitRanges", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.MessageRange]? in - let reader = BufferReader(buffer) - var result: [Api.MessageRange]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageRange.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getStickerSet(stickerset: Api.InputStickerSet, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-928977804) - stickerset.serialize(buffer, true) - serializeInt32(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getStickerSet", parameters: [("stickerset", String(describing: stickerset)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } -} -public extension Api.functions.messages { - static func getStickers(emoticon: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-710552671) - serializeString(emoticon, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getStickers", parameters: [("emoticon", String(describing: emoticon)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Stickers? in - let reader = BufferReader(buffer) - var result: Api.messages.Stickers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Stickers - } - return result - }) - } -} -public extension Api.functions.messages { - static func getSuggestedDialogFilters() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogFilterSuggested]>) { - let buffer = Buffer() - buffer.appendInt32(-1566780372) - - return (FunctionDescription(name: "messages.getSuggestedDialogFilters", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogFilterSuggested]? in - let reader = BufferReader(buffer) - var result: [Api.DialogFilterSuggested]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilterSuggested.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func getUnreadMentions(peer: Api.InputPeer, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1180140658) - peer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(addOffset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(minId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getUnreadMentions", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getUnreadReactions(peer: Api.InputPeer, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-396644838) - peer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(addOffset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(minId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getUnreadReactions", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func getWebPage(url: String, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(852135825) - serializeString(url, buffer: buffer, boxed: false) - serializeInt32(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.getWebPage", parameters: [("url", String(describing: url)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebPage? in - let reader = BufferReader(buffer) - var result: Api.WebPage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.WebPage - } - return result - }) - } -} -public extension Api.functions.messages { - static func getWebPagePreview(flags: Int32, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1956073268) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "messages.getWebPagePreview", parameters: [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in - let reader = BufferReader(buffer) - var result: Api.MessageMedia? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.MessageMedia - } - return result - }) - } -} -public extension Api.functions.messages { - static func hideAllChatJoinRequests(flags: Int32, peer: Api.InputPeer, link: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-528091926) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.hideAllChatJoinRequests", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func hideChatJoinRequest(flags: Int32, peer: Api.InputPeer, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2145904661) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - userId.serialize(buffer, true) - return (FunctionDescription(name: "messages.hideChatJoinRequest", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func hidePeerSettingsBar(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1336717624) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.hidePeerSettingsBar", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func importChatInvite(hash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1817183516) - serializeString(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.importChatInvite", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func initHistoryImport(peer: Api.InputPeer, file: Api.InputFile, mediaCount: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(873008187) - peer.serialize(buffer, true) - file.serialize(buffer, true) - serializeInt32(mediaCount, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.initHistoryImport", parameters: [("peer", String(describing: peer)), ("file", String(describing: file)), ("mediaCount", String(describing: mediaCount))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImport? in - let reader = BufferReader(buffer) - var result: Api.messages.HistoryImport? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImport - } - return result - }) - } -} -public extension Api.functions.messages { - static func installStickerSet(stickerset: Api.InputStickerSet, archived: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-946871200) - stickerset.serialize(buffer, true) - archived.serialize(buffer, true) - return (FunctionDescription(name: "messages.installStickerSet", parameters: [("stickerset", String(describing: stickerset)), ("archived", String(describing: archived))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSetInstallResult? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSetInstallResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSetInstallResult - } - return result - }) - } -} -public extension Api.functions.messages { - static func markDialogUnread(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1031349873) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.markDialogUnread", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func migrateChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1568189671) - serializeInt64(chatId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.migrateChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func prolongWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, queryId: Int64, replyToMsgId: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-362824498) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - bot.serialize(buffer, true) - serializeInt64(queryId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.prolongWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("queryId", String(describing: queryId)), ("replyToMsgId", String(describing: replyToMsgId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func rateTranscribedAudio(peer: Api.InputPeer, msgId: Int32, transcriptionId: Int64, good: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2132608815) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt64(transcriptionId, buffer: buffer, boxed: false) - good.serialize(buffer, true) - return (FunctionDescription(name: "messages.rateTranscribedAudio", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("transcriptionId", String(describing: transcriptionId)), ("good", String(describing: good))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func readDiscussion(peer: Api.InputPeer, msgId: Int32, readMaxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-147740172) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt32(readMaxId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.readDiscussion", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("readMaxId", String(describing: readMaxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func readEncryptedHistory(peer: Api.InputEncryptedChat, maxDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2135648522) - peer.serialize(buffer, true) - serializeInt32(maxDate, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.readEncryptedHistory", parameters: [("peer", String(describing: peer)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func readFeaturedStickers(id: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1527873830) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.readFeaturedStickers", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func readHistory(peer: Api.InputPeer, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(238054714) - peer.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.readHistory", parameters: [("peer", String(describing: peer)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages - } - return result - }) - } -} -public extension Api.functions.messages { - static func readMentions(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(251759059) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.readMentions", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedHistory? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory - } - return result - }) - } -} -public extension Api.functions.messages { - static func readMessageContents(id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(916930423) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.readMessageContents", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedMessages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages - } - return result - }) - } -} -public extension Api.functions.messages { - static func readReactions(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2099097129) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.readReactions", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedHistory? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory - } - return result - }) - } -} -public extension Api.functions.messages { - static func receivedMessages(maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ReceivedNotifyMessage]>) { - let buffer = Buffer() - buffer.appendInt32(94983360) - serializeInt32(maxId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.receivedMessages", parameters: [("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.ReceivedNotifyMessage]? in - let reader = BufferReader(buffer) - var result: [Api.ReceivedNotifyMessage]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.ReceivedNotifyMessage.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func receivedQueue(maxQts: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { - let buffer = Buffer() - buffer.appendInt32(1436924774) - serializeInt32(maxQts, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.receivedQueue", parameters: [("maxQts", String(describing: maxQts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in - let reader = BufferReader(buffer) - var result: [Int64]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - return result - }) - } -} -public extension Api.functions.messages { - static func reorderPinnedDialogs(flags: Int32, folderId: Int32, order: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(991616823) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(folderId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order.count)) - for item in order { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "messages.reorderPinnedDialogs", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func reorderStickerSets(flags: Int32, order: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2016638777) - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order.count)) - for item in order { - serializeInt64(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.reorderStickerSets", parameters: [("flags", String(describing: flags)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func report(peer: Api.InputPeer, id: [Int32], reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1991005362) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - reason.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.report", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func reportEncryptedSpam(peer: Api.InputEncryptedChat) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1259113487) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.reportEncryptedSpam", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func reportSpam(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-820669733) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.reportSpam", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func requestEncryption(userId: Api.InputUser, randomId: Int32, gA: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-162681021) - userId.serialize(buffer, true) - serializeInt32(randomId, buffer: buffer, boxed: false) - serializeBytes(gA, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.requestEncryption", parameters: [("userId", String(describing: userId)), ("randomId", String(describing: randomId)), ("gA", String(describing: gA))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedChat? in - let reader = BufferReader(buffer) - var result: Api.EncryptedChat? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EncryptedChat - } - return result - }) - } -} -public extension Api.functions.messages { - static func requestSimpleWebView(flags: Int32, bot: Api.InputUser, url: String, themeParams: Api.DataJSON?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1790652275) - serializeInt32(flags, buffer: buffer, boxed: false) - bot.serialize(buffer, true) - serializeString(url, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.requestSimpleWebView", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("themeParams", String(describing: themeParams))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SimpleWebViewResult? in - let reader = BufferReader(buffer) - var result: Api.SimpleWebViewResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.SimpleWebViewResult - } - return result - }) - } -} -public extension Api.functions.messages { - static func requestUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(428848198) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.requestUrlAuth", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("buttonId", String(describing: buttonId)), ("url", String(describing: url))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in - let reader = BufferReader(buffer) - var result: Api.UrlAuthResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.UrlAuthResult - } - return result - }) - } -} -public extension Api.functions.messages { - static func requestWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, url: String?, startParam: String?, themeParams: Api.DataJSON?, replyToMsgId: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1850648527) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - bot.serialize(buffer, true) - if Int(flags) & Int(1 << 1) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.requestWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("replyToMsgId", String(describing: replyToMsgId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in - let reader = BufferReader(buffer) - var result: Api.WebViewResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.WebViewResult - } - return result - }) - } -} -public extension Api.functions.messages { - static func saveDefaultSendAs(peer: Api.InputPeer, sendAs: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-855777386) - peer.serialize(buffer, true) - sendAs.serialize(buffer, true) - return (FunctionDescription(name: "messages.saveDefaultSendAs", parameters: [("peer", String(describing: peer)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func saveDraft(flags: Int32, replyToMsgId: Int32?, peer: Api.InputPeer, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1137057461) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - peer.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "messages.saveDraft", parameters: [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("peer", String(describing: peer)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func saveGif(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(846868683) - id.serialize(buffer, true) - unsave.serialize(buffer, true) - return (FunctionDescription(name: "messages.saveGif", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func saveRecentSticker(flags: Int32, id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(958863608) - serializeInt32(flags, buffer: buffer, boxed: false) - id.serialize(buffer, true) - unsave.serialize(buffer, true) - return (FunctionDescription(name: "messages.saveRecentSticker", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func search(flags: Int32, peer: Api.InputPeer, q: String, fromId: Api.InputPeer?, topMsgId: Int32?, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1593989278) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeString(q, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {fromId!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} - filter.serialize(buffer, true) - serializeInt32(minDate, buffer: buffer, boxed: false) - serializeInt32(maxDate, buffer: buffer, boxed: false) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(addOffset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(minId, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.search", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("q", String(describing: q)), ("fromId", String(describing: fromId)), ("topMsgId", String(describing: topMsgId)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func searchGlobal(flags: Int32, folderId: Int32?, q: String, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1271290010) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} - serializeString(q, buffer: buffer, boxed: false) - filter.serialize(buffer, true) - serializeInt32(minDate, buffer: buffer, boxed: false) - serializeInt32(maxDate, buffer: buffer, boxed: false) - serializeInt32(offsetRate, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.searchGlobal", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("q", String(describing: q)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetRate", String(describing: offsetRate)), ("offsetPeer", String(describing: offsetPeer)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func searchSentMedia(q: String, filter: Api.MessagesFilter, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(276705696) - serializeString(q, buffer: buffer, boxed: false) - filter.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.searchSentMedia", parameters: [("q", String(describing: q)), ("filter", String(describing: filter)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.messages { - static func searchStickerSets(flags: Int32, q: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(896555914) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(q, buffer: buffer, boxed: false) - serializeInt64(hash, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.searchStickerSets", parameters: [("flags", String(describing: flags)), ("q", String(describing: q)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FoundStickerSets? in - let reader = BufferReader(buffer) - var result: Api.messages.FoundStickerSets? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.FoundStickerSets - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendEncrypted(flags: Int32, peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1157265941) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeBytes(data, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.sendEncrypted", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in - let reader = BufferReader(buffer) - var result: Api.messages.SentEncryptedMessage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendEncryptedFile(flags: Int32, peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer, file: Api.InputEncryptedFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1431914525) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeBytes(data, buffer: buffer, boxed: false) - file.serialize(buffer, true) - return (FunctionDescription(name: "messages.sendEncryptedFile", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in - let reader = BufferReader(buffer) - var result: Api.messages.SentEncryptedMessage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendEncryptedService(peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(852769188) - peer.serialize(buffer, true) - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeBytes(data, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.sendEncryptedService", parameters: [("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in - let reader = BufferReader(buffer) - var result: Api.messages.SentEncryptedMessage? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendInlineBotResult(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, randomId: Int64, queryId: Int64, id: String, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2057376407) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - serializeString(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.sendInlineBotResult", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("randomId", String(describing: randomId)), ("queryId", String(describing: queryId)), ("id", String(describing: id)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendMedia(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, media: Api.InputMedia, message: String, randomId: Int64, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-497026848) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - media.serialize(buffer, true) - serializeString(message, buffer: buffer, boxed: false) - serializeInt64(randomId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.sendMedia", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("media", String(describing: media)), ("message", String(describing: message)), ("randomId", String(describing: randomId)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendMessage(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, message: String, randomId: Int64, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(228423076) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - serializeString(message, buffer: buffer, boxed: false) - serializeInt64(randomId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.sendMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("message", String(describing: message)), ("randomId", String(describing: randomId)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendMultiMedia(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, multiMedia: [Api.InputSingleMedia], scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-134016113) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(multiMedia.count)) - for item in multiMedia { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.sendMultiMedia", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("multiMedia", String(describing: multiMedia)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, reaction: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(627641572) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.sendReaction", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reaction", String(describing: reaction))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1120369398) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.sendScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendScreenshotNotification(peer: Api.InputPeer, replyToMsgId: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-914493408) - peer.serialize(buffer, true) - serializeInt32(replyToMsgId, buffer: buffer, boxed: false) - serializeInt64(randomId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.sendScreenshotNotification", parameters: [("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendVote(peer: Api.InputPeer, msgId: Int32, options: [Buffer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(283795844) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(options.count)) - for item in options { - serializeBytes(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.sendVote", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("options", String(describing: options))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendWebViewData(bot: Api.InputUser, randomId: Int64, buttonText: String, data: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-603831608) - bot.serialize(buffer, true) - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeString(buttonText, buffer: buffer, boxed: false) - serializeString(data, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.sendWebViewData", parameters: [("bot", String(describing: bot)), ("randomId", String(describing: randomId)), ("buttonText", String(describing: buttonText)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func sendWebViewResultMessage(botQueryId: String, result: Api.InputBotInlineResult) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(172168437) - serializeString(botQueryId, buffer: buffer, boxed: false) - result.serialize(buffer, true) - return (FunctionDescription(name: "messages.sendWebViewResultMessage", parameters: [("botQueryId", String(describing: botQueryId)), ("result", String(describing: result))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewMessageSent? in - let reader = BufferReader(buffer) - var result: Api.WebViewMessageSent? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.WebViewMessageSent - } - return result - }) - } -} -public extension Api.functions.messages { - static func setBotCallbackAnswer(flags: Int32, queryId: Int64, message: String?, url: String?, cacheTime: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-712043766) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(message!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} - serializeInt32(cacheTime, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setBotCallbackAnswer", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("message", String(describing: message)), ("url", String(describing: url)), ("cacheTime", String(describing: cacheTime))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setBotPrecheckoutResults(flags: Int32, queryId: Int64, error: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(163765653) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(error!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "messages.setBotPrecheckoutResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("error", String(describing: error))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setBotShippingResults(flags: Int32, queryId: Int64, error: String?, shippingOptions: [Api.ShippingOption]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-436833542) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(error!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(shippingOptions!.count)) - for item in shippingOptions! { - item.serialize(buffer, true) - }} - return (FunctionDescription(name: "messages.setBotShippingResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("error", String(describing: error)), ("shippingOptions", String(describing: shippingOptions))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setChatAvailableReactions(peer: Api.InputPeer, availableReactions: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(335875750) - peer.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(availableReactions.count)) - for item in availableReactions { - serializeString(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func setChatTheme(peer: Api.InputPeer, emoticon: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-432283329) - peer.serialize(buffer, true) - serializeString(emoticon, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setChatTheme", parameters: [("peer", String(describing: peer)), ("emoticon", String(describing: emoticon))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func setDefaultReaction(reaction: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-647969580) - serializeString(reaction, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setDefaultReaction", parameters: [("reaction", String(describing: reaction))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setEncryptedTyping(peer: Api.InputEncryptedChat, typing: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2031374829) - peer.serialize(buffer, true) - typing.serialize(buffer, true) - return (FunctionDescription(name: "messages.setEncryptedTyping", parameters: [("peer", String(describing: peer)), ("typing", String(describing: typing))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setGameScore(flags: Int32, peer: Api.InputPeer, id: Int32, userId: Api.InputUser, score: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1896289088) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - serializeInt32(score, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setGameScore", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("score", String(describing: score))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func setHistoryTTL(peer: Api.InputPeer, period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1207017500) - peer.serialize(buffer, true) - serializeInt32(period, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setHistoryTTL", parameters: [("peer", String(describing: peer)), ("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func setInlineBotResults(flags: Int32, queryId: Int64, results: [Api.InputBotInlineResult], cacheTime: Int32, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-346119674) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(results.count)) - for item in results { - item.serialize(buffer, true) - } - serializeInt32(cacheTime, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 3) != 0 {switchPm!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.setInlineBotResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("results", String(describing: results)), ("cacheTime", String(describing: cacheTime)), ("nextOffset", String(describing: nextOffset)), ("switchPm", String(describing: switchPm))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setInlineGameScore(flags: Int32, id: Api.InputBotInlineMessageID, userId: Api.InputUser, score: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(363700068) - serializeInt32(flags, buffer: buffer, boxed: false) - id.serialize(buffer, true) - userId.serialize(buffer, true) - serializeInt32(score, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.setInlineGameScore", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("score", String(describing: score))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func setTyping(flags: Int32, peer: Api.InputPeer, topMsgId: Int32?, action: Api.SendMessageAction) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1486110434) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} - action.serialize(buffer, true) - return (FunctionDescription(name: "messages.setTyping", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("topMsgId", String(describing: topMsgId)), ("action", String(describing: action))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func startBot(bot: Api.InputUser, peer: Api.InputPeer, randomId: Int64, startParam: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-421563528) - bot.serialize(buffer, true) - peer.serialize(buffer, true) - serializeInt64(randomId, buffer: buffer, boxed: false) - serializeString(startParam, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.startBot", parameters: [("bot", String(describing: bot)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("startParam", String(describing: startParam))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func startHistoryImport(peer: Api.InputPeer, importId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1271008444) - peer.serialize(buffer, true) - serializeInt64(importId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.startHistoryImport", parameters: [("peer", String(describing: peer)), ("importId", String(describing: importId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func toggleBotInAttachMenu(bot: Api.InputUser, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(451818415) - bot.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "messages.toggleBotInAttachMenu", parameters: [("bot", String(describing: bot)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func toggleDialogPin(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1489903017) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.toggleDialogPin", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func toggleNoForwards(peer: Api.InputPeer, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1323389022) - peer.serialize(buffer, true) - enabled.serialize(buffer, true) - return (FunctionDescription(name: "messages.toggleNoForwards", parameters: [("peer", String(describing: peer)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func toggleStickerSets(flags: Int32, stickersets: [Api.InputStickerSet]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1257951254) - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stickersets.count)) - for item in stickersets { - item.serialize(buffer, true) - } - return (FunctionDescription(name: "messages.toggleStickerSets", parameters: [("flags", String(describing: flags)), ("stickersets", String(describing: stickersets))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func transcribeAudio(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(647928393) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.transcribeAudio", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranscribedAudio? in - let reader = BufferReader(buffer) - var result: Api.messages.TranscribedAudio? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.TranscribedAudio - } - return result - }) - } -} -public extension Api.functions.messages { - static func translateText(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, text: String?, fromLang: String?, toLang: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(617508334) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(text!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeString(fromLang!, buffer: buffer, boxed: false)} - serializeString(toLang, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.translateText", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("text", String(describing: text)), ("fromLang", String(describing: fromLang)), ("toLang", String(describing: toLang))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranslatedText? in - let reader = BufferReader(buffer) - var result: Api.messages.TranslatedText? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.TranslatedText - } - return result - }) - } -} -public extension Api.functions.messages { - static func uninstallStickerSet(stickerset: Api.InputStickerSet) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-110209570) - stickerset.serialize(buffer, true) - return (FunctionDescription(name: "messages.uninstallStickerSet", parameters: [("stickerset", String(describing: stickerset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func unpinAllMessages(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-265962357) - peer.serialize(buffer, true) - return (FunctionDescription(name: "messages.unpinAllMessages", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in - let reader = BufferReader(buffer) - var result: Api.messages.AffectedHistory? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory - } - return result - }) - } -} -public extension Api.functions.messages { - static func updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(450142282) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} - return (FunctionDescription(name: "messages.updateDialogFilter", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("filter", String(describing: filter))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func updateDialogFiltersOrder(order: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-983318044) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(order.count)) - for item in order { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "messages.updateDialogFiltersOrder", parameters: [("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.messages { - static func updatePinnedMessage(flags: Int32, peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-760547348) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.updatePinnedMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.messages { - static func uploadEncryptedFile(peer: Api.InputEncryptedChat, file: Api.InputEncryptedFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1347929239) - peer.serialize(buffer, true) - file.serialize(buffer, true) - return (FunctionDescription(name: "messages.uploadEncryptedFile", parameters: [("peer", String(describing: peer)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedFile? in - let reader = BufferReader(buffer) - var result: Api.EncryptedFile? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.EncryptedFile - } - return result - }) - } -} -public extension Api.functions.messages { - static func uploadImportedMedia(peer: Api.InputPeer, importId: Int64, fileName: String, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(713433234) - peer.serialize(buffer, true) - serializeInt64(importId, buffer: buffer, boxed: false) - serializeString(fileName, buffer: buffer, boxed: false) - media.serialize(buffer, true) - return (FunctionDescription(name: "messages.uploadImportedMedia", parameters: [("peer", String(describing: peer)), ("importId", String(describing: importId)), ("fileName", String(describing: fileName)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in - let reader = BufferReader(buffer) - var result: Api.MessageMedia? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.MessageMedia - } - return result - }) - } -} -public extension Api.functions.messages { - static func uploadMedia(peer: Api.InputPeer, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1369162417) - peer.serialize(buffer, true) - media.serialize(buffer, true) - return (FunctionDescription(name: "messages.uploadMedia", parameters: [("peer", String(describing: peer)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in - let reader = BufferReader(buffer) - var result: Api.MessageMedia? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.MessageMedia - } - return result - }) - } -} -public extension Api.functions.payments { - static func assignAppStoreTransaction(flags: Int32, receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(224186320) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeBytes(receipt, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("receipt", String(describing: receipt))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.payments { - static func assignPlayMarketTransaction(purchaseToken: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1336560365) - serializeString(purchaseToken, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.assignPlayMarketTransaction", parameters: [("purchaseToken", String(describing: purchaseToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.payments { - static func canPurchasePremium() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1435856696) - - return (FunctionDescription(name: "payments.canPurchasePremium", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.payments { - static func clearSavedInfo(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-667062079) - serializeInt32(flags, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.clearSavedInfo", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.payments { - static func exportInvoice(invoiceMedia: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(261206117) - invoiceMedia.serialize(buffer, true) - return (FunctionDescription(name: "payments.exportInvoice", parameters: [("invoiceMedia", String(describing: invoiceMedia))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.ExportedInvoice? in - let reader = BufferReader(buffer) - var result: Api.payments.ExportedInvoice? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.ExportedInvoice - } - return result - }) - } -} -public extension Api.functions.payments { - static func getBankCardData(number: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(779736953) - serializeString(number, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.getBankCardData", parameters: [("number", String(describing: number))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.BankCardData? in - let reader = BufferReader(buffer) - var result: Api.payments.BankCardData? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.BankCardData - } - return result - }) - } -} -public extension Api.functions.payments { - static func getPaymentForm(flags: Int32, invoice: Api.InputInvoice, themeParams: Api.DataJSON?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(924093883) - serializeInt32(flags, buffer: buffer, boxed: false) - invoice.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)} - return (FunctionDescription(name: "payments.getPaymentForm", parameters: [("flags", String(describing: flags)), ("invoice", String(describing: invoice)), ("themeParams", String(describing: themeParams))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentForm? in - let reader = BufferReader(buffer) - var result: Api.payments.PaymentForm? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.PaymentForm - } - return result - }) - } -} -public extension Api.functions.payments { - static func getPaymentReceipt(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(611897804) - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.getPaymentReceipt", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentReceipt? in - let reader = BufferReader(buffer) - var result: Api.payments.PaymentReceipt? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.PaymentReceipt - } - return result - }) - } -} -public extension Api.functions.payments { - static func getSavedInfo() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(578650699) - - return (FunctionDescription(name: "payments.getSavedInfo", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedInfo? in - let reader = BufferReader(buffer) - var result: Api.payments.SavedInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.SavedInfo - } - return result - }) - } -} -public extension Api.functions.payments { - static func requestRecurringPayment(userId: Api.InputUser, recurringInitCharge: String, invoiceMedia: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(342791565) - userId.serialize(buffer, true) - serializeString(recurringInitCharge, buffer: buffer, boxed: false) - invoiceMedia.serialize(buffer, true) - return (FunctionDescription(name: "payments.requestRecurringPayment", parameters: [("userId", String(describing: userId)), ("recurringInitCharge", String(describing: recurringInitCharge)), ("invoiceMedia", String(describing: invoiceMedia))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.payments { - static func sendPaymentForm(flags: Int32, formId: Int64, invoice: Api.InputInvoice, requestedInfoId: String?, shippingOptionId: String?, credentials: Api.InputPaymentCredentials, tipAmount: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(755192367) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(formId, buffer: buffer, boxed: false) - invoice.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {serializeString(requestedInfoId!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} - credentials.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {serializeInt64(tipAmount!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "payments.sendPaymentForm", parameters: [("flags", String(describing: flags)), ("formId", String(describing: formId)), ("invoice", String(describing: invoice)), ("requestedInfoId", String(describing: requestedInfoId)), ("shippingOptionId", String(describing: shippingOptionId)), ("credentials", String(describing: credentials)), ("tipAmount", String(describing: tipAmount))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentResult? in - let reader = BufferReader(buffer) - var result: Api.payments.PaymentResult? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.PaymentResult - } - return result - }) - } -} -public extension Api.functions.payments { - static func validateRequestedInfo(flags: Int32, invoice: Api.InputInvoice, info: Api.PaymentRequestedInfo) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1228345045) - serializeInt32(flags, buffer: buffer, boxed: false) - invoice.serialize(buffer, true) - info.serialize(buffer, true) - return (FunctionDescription(name: "payments.validateRequestedInfo", parameters: [("flags", String(describing: flags)), ("invoice", String(describing: invoice)), ("info", String(describing: info))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.ValidatedRequestedInfo? in - let reader = BufferReader(buffer) - var result: Api.payments.ValidatedRequestedInfo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.payments.ValidatedRequestedInfo - } - return result - }) - } -} -public extension Api.functions.phone { - static func acceptCall(peer: Api.InputPhoneCall, gB: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1003664544) - peer.serialize(buffer, true) - serializeBytes(gB, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - return (FunctionDescription(name: "phone.acceptCall", parameters: [("peer", String(describing: peer)), ("gB", String(describing: gB)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in - let reader = BufferReader(buffer) - var result: Api.phone.PhoneCall? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall - } - return result - }) - } -} -public extension Api.functions.phone { - static func checkGroupCall(call: Api.InputGroupCall, sources: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) { - let buffer = Buffer() - buffer.appendInt32(-1248003721) - call.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sources.count)) - for item in sources { - serializeInt32(item, buffer: buffer, boxed: false) - } - return (FunctionDescription(name: "phone.checkGroupCall", parameters: [("call", String(describing: call)), ("sources", String(describing: sources))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in - let reader = BufferReader(buffer) - var result: [Int32]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } - return result - }) - } -} -public extension Api.functions.phone { - static func confirmCall(peer: Api.InputPhoneCall, gA: Buffer, keyFingerprint: Int64, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(788404002) - peer.serialize(buffer, true) - serializeBytes(gA, buffer: buffer, boxed: false) - serializeInt64(keyFingerprint, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - return (FunctionDescription(name: "phone.confirmCall", parameters: [("peer", String(describing: peer)), ("gA", String(describing: gA)), ("keyFingerprint", String(describing: keyFingerprint)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in - let reader = BufferReader(buffer) - var result: Api.phone.PhoneCall? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall - } - return result - }) - } -} -public extension Api.functions.phone { - static func createGroupCall(flags: Int32, peer: Api.InputPeer, randomId: Int32, title: String?, scheduleDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1221445336) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(randomId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "phone.createGroupCall", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("title", String(describing: title)), ("scheduleDate", String(describing: scheduleDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func discardCall(flags: Int32, peer: Api.InputPhoneCall, duration: Int32, reason: Api.PhoneCallDiscardReason, connectionId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1295269440) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(duration, buffer: buffer, boxed: false) - reason.serialize(buffer, true) - serializeInt64(connectionId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.discardCall", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("duration", String(describing: duration)), ("reason", String(describing: reason)), ("connectionId", String(describing: connectionId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func discardGroupCall(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2054648117) - call.serialize(buffer, true) - return (FunctionDescription(name: "phone.discardGroupCall", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func editGroupCallParticipant(flags: Int32, call: Api.InputGroupCall, participant: Api.InputPeer, muted: Api.Bool?, volume: Int32?, raiseHand: Api.Bool?, videoStopped: Api.Bool?, videoPaused: Api.Bool?, presentationPaused: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1524155713) - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - participant.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {muted!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {raiseHand!.serialize(buffer, true)} - if Int(flags) & Int(1 << 3) != 0 {videoStopped!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {videoPaused!.serialize(buffer, true)} - if Int(flags) & Int(1 << 5) != 0 {presentationPaused!.serialize(buffer, true)} - return (FunctionDescription(name: "phone.editGroupCallParticipant", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("participant", String(describing: participant)), ("muted", String(describing: muted)), ("volume", String(describing: volume)), ("raiseHand", String(describing: raiseHand)), ("videoStopped", String(describing: videoStopped)), ("videoPaused", String(describing: videoPaused)), ("presentationPaused", String(describing: presentationPaused))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func editGroupCallTitle(call: Api.InputGroupCall, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(480685066) - call.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.editGroupCallTitle", parameters: [("call", String(describing: call)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func exportGroupCallInvite(flags: Int32, call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-425040769) - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - return (FunctionDescription(name: "phone.exportGroupCallInvite", parameters: [("flags", String(describing: flags)), ("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.ExportedGroupCallInvite? in - let reader = BufferReader(buffer) - var result: Api.phone.ExportedGroupCallInvite? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.ExportedGroupCallInvite - } - return result - }) - } -} -public extension Api.functions.phone { - static func getCallConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1430593449) - - return (FunctionDescription(name: "phone.getCallConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.DataJSON? in - let reader = BufferReader(buffer) - var result: Api.DataJSON? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.DataJSON - } - return result - }) - } -} -public extension Api.functions.phone { - static func getGroupCall(call: Api.InputGroupCall, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(68699611) - call.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.getGroupCall", parameters: [("call", String(describing: call)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCall? in - let reader = BufferReader(buffer) - var result: Api.phone.GroupCall? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.GroupCall - } - return result - }) - } -} -public extension Api.functions.phone { - static func getGroupCallJoinAs(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-277077702) - peer.serialize(buffer, true) - return (FunctionDescription(name: "phone.getGroupCallJoinAs", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.JoinAsPeers? in - let reader = BufferReader(buffer) - var result: Api.phone.JoinAsPeers? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.JoinAsPeers - } - return result - }) - } -} -public extension Api.functions.phone { - static func getGroupCallStreamChannels(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(447879488) - call.serialize(buffer, true) - return (FunctionDescription(name: "phone.getGroupCallStreamChannels", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCallStreamChannels? in - let reader = BufferReader(buffer) - var result: Api.phone.GroupCallStreamChannels? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.GroupCallStreamChannels - } - return result - }) - } -} -public extension Api.functions.phone { - static func getGroupCallStreamRtmpUrl(peer: Api.InputPeer, revoke: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-558650433) - peer.serialize(buffer, true) - revoke.serialize(buffer, true) - return (FunctionDescription(name: "phone.getGroupCallStreamRtmpUrl", parameters: [("peer", String(describing: peer)), ("revoke", String(describing: revoke))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCallStreamRtmpUrl? in - let reader = BufferReader(buffer) - var result: Api.phone.GroupCallStreamRtmpUrl? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.GroupCallStreamRtmpUrl - } - return result - }) - } -} -public extension Api.functions.phone { - static func getGroupParticipants(call: Api.InputGroupCall, ids: [Api.InputPeer], sources: [Int32], offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-984033109) - call.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(ids.count)) - for item in ids { + buffer.appendInt32(Int32(topPosters.count)) + for item in topPosters { item.serialize(buffer, true) } buffer.appendInt32(481674261) - buffer.appendInt32(Int32(sources.count)) - for item in sources { - serializeInt32(item, buffer: buffer, boxed: false) + buffer.appendInt32(Int32(topAdmins.count)) + for item in topAdmins { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(topInviters.count)) + for item in topInviters { + item.serialize(buffer, true) } - serializeString(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.getGroupParticipants", parameters: [("call", String(describing: call)), ("ids", String(describing: ids)), ("sources", String(describing: sources)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupParticipants? in - let reader = BufferReader(buffer) - var result: Api.phone.GroupParticipants? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.GroupParticipants - } - return result - }) - } -} -public extension Api.functions.phone { - static func inviteToGroupCall(call: Api.InputGroupCall, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(2067345760) - call.serialize(buffer, true) buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { item.serialize(buffer, true) } - return (FunctionDescription(name: "phone.inviteToGroupCall", parameters: [("call", String(describing: call)), ("users", String(describing: users))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users): + return ("megagroupStats", [("period", String(describing: period)), ("members", String(describing: members)), ("messages", String(describing: messages)), ("viewers", String(describing: viewers)), ("posters", String(describing: posters)), ("growthGraph", String(describing: growthGraph)), ("membersGraph", String(describing: membersGraph)), ("newMembersBySourceGraph", String(describing: newMembersBySourceGraph)), ("languagesGraph", String(describing: languagesGraph)), ("messagesGraph", String(describing: messagesGraph)), ("actionsGraph", String(describing: actionsGraph)), ("topHoursGraph", String(describing: topHoursGraph)), ("weekdaysGraph", String(describing: weekdaysGraph)), ("topPosters", String(describing: topPosters)), ("topAdmins", String(describing: topAdmins)), ("topInviters", String(describing: topInviters)), ("users", String(describing: users))]) + } + } + + public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? { + var _1: Api.StatsDateRangeDays? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays + } + var _2: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _3: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _4: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _5: Api.StatsAbsValueAndPrev? + if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev + } + var _6: Api.StatsGraph? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _7: Api.StatsGraph? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _8: Api.StatsGraph? + if let signature = reader.readInt32() { + _8 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _9: Api.StatsGraph? + if let signature = reader.readInt32() { + _9 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _10: Api.StatsGraph? + if let signature = reader.readInt32() { + _10 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _11: Api.StatsGraph? + if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _12: Api.StatsGraph? + if let signature = reader.readInt32() { + _12 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _13: Api.StatsGraph? + if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + var _14: [Api.StatsGroupTopPoster]? + if let _ = reader.readInt32() { + _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self) + } + var _15: [Api.StatsGroupTopAdmin]? + if let _ = reader.readInt32() { + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self) + } + var _16: [Api.StatsGroupTopInviter]? + if let _ = reader.readInt32() { + _16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self) + } + var _17: [Api.User]? + if let _ = reader.readInt32() { + _17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = _10 != nil + let _c11 = _11 != nil + let _c12 = _12 != nil + let _c13 = _13 != nil + let _c14 = _14 != nil + let _c15 = _15 != nil + let _c16 = _16 != nil + let _c17 = _17 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 { + return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!) + } + else { + return nil + } + } + + } } -public extension Api.functions.phone { - static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, inviteHash: String?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1322057861) - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - joinAs.serialize(buffer, true) - if Int(flags) & Int(1 << 1) != 0 {serializeString(inviteHash!, buffer: buffer, boxed: false)} - params.serialize(buffer, true) - return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinAs", String(describing: joinAs)), ("inviteHash", String(describing: inviteHash)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func joinGroupCallPresentation(call: Api.InputGroupCall, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-873829436) - call.serialize(buffer, true) - params.serialize(buffer, true) - return (FunctionDescription(name: "phone.joinGroupCallPresentation", parameters: [("call", String(describing: call)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func leaveGroupCall(call: Api.InputGroupCall, source: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1342404601) - call.serialize(buffer, true) - serializeInt32(source, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.leaveGroupCall", parameters: [("call", String(describing: call)), ("source", String(describing: source))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func leaveGroupCallPresentation(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(475058500) - call.serialize(buffer, true) - return (FunctionDescription(name: "phone.leaveGroupCallPresentation", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func receivedCall(peer: Api.InputPhoneCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(399855457) - peer.serialize(buffer, true) - return (FunctionDescription(name: "phone.receivedCall", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.phone { - static func requestCall(flags: Int32, userId: Api.InputUser, randomId: Int32, gAHash: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1124046573) - serializeInt32(flags, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - serializeInt32(randomId, buffer: buffer, boxed: false) - serializeBytes(gAHash, buffer: buffer, boxed: false) - `protocol`.serialize(buffer, true) - return (FunctionDescription(name: "phone.requestCall", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("randomId", String(describing: randomId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in - let reader = BufferReader(buffer) - var result: Api.phone.PhoneCall? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall - } - return result - }) - } -} -public extension Api.functions.phone { - static func saveCallDebug(peer: Api.InputPhoneCall, debug: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(662363518) - peer.serialize(buffer, true) - debug.serialize(buffer, true) - return (FunctionDescription(name: "phone.saveCallDebug", parameters: [("peer", String(describing: peer)), ("debug", String(describing: debug))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.phone { - static func saveCallLog(peer: Api.InputPhoneCall, file: Api.InputFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1092913030) - peer.serialize(buffer, true) - file.serialize(buffer, true) - return (FunctionDescription(name: "phone.saveCallLog", parameters: [("peer", String(describing: peer)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.phone { - static func saveDefaultGroupCallJoinAs(peer: Api.InputPeer, joinAs: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1465786252) - peer.serialize(buffer, true) - joinAs.serialize(buffer, true) - return (FunctionDescription(name: "phone.saveDefaultGroupCallJoinAs", parameters: [("peer", String(describing: peer)), ("joinAs", String(describing: joinAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.phone { - static func sendSignalingData(peer: Api.InputPhoneCall, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-8744061) - peer.serialize(buffer, true) - serializeBytes(data, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.sendSignalingData", parameters: [("peer", String(describing: peer)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.phone { - static func setCallRating(flags: Int32, peer: Api.InputPhoneCall, rating: Int32, comment: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1508562471) - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt32(rating, buffer: buffer, boxed: false) - serializeString(comment, buffer: buffer, boxed: false) - return (FunctionDescription(name: "phone.setCallRating", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("rating", String(describing: rating)), ("comment", String(describing: comment))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func startScheduledGroupCall(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1451287362) - call.serialize(buffer, true) - return (FunctionDescription(name: "phone.startScheduledGroupCall", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func toggleGroupCallRecord(flags: Int32, call: Api.InputGroupCall, title: String?, videoPortrait: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-248985848) - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {videoPortrait!.serialize(buffer, true)} - return (FunctionDescription(name: "phone.toggleGroupCallRecord", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("title", String(describing: title)), ("videoPortrait", String(describing: videoPortrait))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func toggleGroupCallSettings(flags: Int32, call: Api.InputGroupCall, joinMuted: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1958458429) - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - if Int(flags) & Int(1 << 0) != 0 {joinMuted!.serialize(buffer, true)} - return (FunctionDescription(name: "phone.toggleGroupCallSettings", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinMuted", String(describing: joinMuted))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.phone { - static func toggleGroupCallStartSubscription(call: Api.InputGroupCall, subscribed: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(563885286) - call.serialize(buffer, true) - subscribed.serialize(buffer, true) - return (FunctionDescription(name: "phone.toggleGroupCallStartSubscription", parameters: [("call", String(describing: call)), ("subscribed", String(describing: subscribed))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.photos { - static func deletePhotos(id: [Api.InputPhoto]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { - let buffer = Buffer() - buffer.appendInt32(-2016444625) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { - item.serialize(buffer, true) +public extension Api.stats { + enum MessageStats: TypeConstructorDescription { + case messageStats(viewsGraph: Api.StatsGraph) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .messageStats(let viewsGraph): + if boxed { + buffer.appendInt32(-1986399595) } - return (FunctionDescription(name: "photos.deletePhotos", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in - let reader = BufferReader(buffer) - var result: [Int64]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - return result - }) - } + viewsGraph.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .messageStats(let viewsGraph): + return ("messageStats", [("viewsGraph", String(describing: viewsGraph))]) + } + } + + public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? { + var _1: Api.StatsGraph? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + let _c1 = _1 != nil + if _c1 { + return Api.stats.MessageStats.messageStats(viewsGraph: _1!) + } + else { + return nil + } + } + + } } -public extension Api.functions.photos { - static func getUserPhotos(userId: Api.InputUser, offset: Int32, maxId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1848823128) - userId.serialize(buffer, true) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt64(maxId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "photos.getUserPhotos", parameters: [("userId", String(describing: userId)), ("offset", String(describing: offset)), ("maxId", String(describing: maxId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photos? in - let reader = BufferReader(buffer) - var result: Api.photos.Photos? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.photos.Photos - } - return result - }) - } -} -public extension Api.functions.photos { - static func updateProfilePhoto(id: Api.InputPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1926525996) - id.serialize(buffer, true) - return (FunctionDescription(name: "photos.updateProfilePhoto", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in - let reader = BufferReader(buffer) - var result: Api.photos.Photo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.photos.Photo - } - return result - }) - } -} -public extension Api.functions.photos { - static func uploadProfilePhoto(flags: Int32, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1980559511) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)} - if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "photos.uploadProfilePhoto", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in - let reader = BufferReader(buffer) - var result: Api.photos.Photo? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.photos.Photo - } - return result - }) - } -} -public extension Api.functions.stats { - static func getBroadcastStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1421720550) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - return (FunctionDescription(name: "stats.getBroadcastStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastStats? in - let reader = BufferReader(buffer) - var result: Api.stats.BroadcastStats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastStats - } - return result - }) - } -} -public extension Api.functions.stats { - static func getMegagroupStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-589330937) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - return (FunctionDescription(name: "stats.getMegagroupStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.MegagroupStats? in - let reader = BufferReader(buffer) - var result: Api.stats.MegagroupStats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.stats.MegagroupStats - } - return result - }) - } -} -public extension Api.functions.stats { - static func getMessagePublicForwards(channel: Api.InputChannel, msgId: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1445996571) - channel.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt32(offsetRate, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "stats.getMessagePublicForwards", parameters: [("channel", String(describing: channel)), ("msgId", String(describing: msgId)), ("offsetRate", String(describing: offsetRate)), ("offsetPeer", String(describing: offsetPeer)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in - let reader = BufferReader(buffer) - var result: Api.messages.Messages? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Messages - } - return result - }) - } -} -public extension Api.functions.stats { - static func getMessageStats(flags: Int32, channel: Api.InputChannel, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1226791947) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "stats.getMessageStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.MessageStats? in - let reader = BufferReader(buffer) - var result: Api.stats.MessageStats? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.stats.MessageStats - } - return result - }) - } -} -public extension Api.functions.stats { - static func loadAsyncGraph(flags: Int32, token: String, x: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1646092192) - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(token, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt64(x!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "stats.loadAsyncGraph", parameters: [("flags", String(describing: flags)), ("token", String(describing: token)), ("x", String(describing: x))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StatsGraph? in - let reader = BufferReader(buffer) - var result: Api.StatsGraph? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.StatsGraph - } - return result - }) - } -} -public extension Api.functions.stickers { - static func addStickerToSet(stickerset: Api.InputStickerSet, sticker: Api.InputStickerSetItem) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2041315650) - stickerset.serialize(buffer, true) - sticker.serialize(buffer, true) - return (FunctionDescription(name: "stickers.addStickerToSet", parameters: [("stickerset", String(describing: stickerset)), ("sticker", String(describing: sticker))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } -} -public extension Api.functions.stickers { - static func changeStickerPosition(sticker: Api.InputDocument, position: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-4795190) - sticker.serialize(buffer, true) - serializeInt32(position, buffer: buffer, boxed: false) - return (FunctionDescription(name: "stickers.changeStickerPosition", parameters: [("sticker", String(describing: sticker)), ("position", String(describing: position))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } -} -public extension Api.functions.stickers { - static func checkShortName(shortName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(676017721) +public extension Api.stickers { + enum SuggestedShortName: TypeConstructorDescription { + case suggestedShortName(shortName: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .suggestedShortName(let shortName): + if boxed { + buffer.appendInt32(-2046910401) + } serializeString(shortName, buffer: buffer, boxed: false) - return (FunctionDescription(name: "stickers.checkShortName", parameters: [("shortName", String(describing: shortName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .suggestedShortName(let shortName): + return ("suggestedShortName", [("shortName", String(describing: shortName))]) + } + } + + public static func parse_suggestedShortName(_ reader: BufferReader) -> SuggestedShortName? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.stickers.SuggestedShortName.suggestedShortName(shortName: _1!) + } + else { + return nil + } + } + + } } -public extension Api.functions.stickers { - static func createStickerSet(flags: Int32, userId: Api.InputUser, title: String, shortName: String, thumb: Api.InputDocument?, stickers: [Api.InputStickerSetItem], software: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1876841625) - serializeInt32(flags, buffer: buffer, boxed: false) - userId.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - serializeString(shortName, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {thumb!.serialize(buffer, true)} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stickers.count)) - for item in stickers { - item.serialize(buffer, true) +public extension Api.storage { + enum FileType: TypeConstructorDescription { + case fileGif + case fileJpeg + case fileMov + case fileMp3 + case fileMp4 + case filePartial + case filePdf + case filePng + case fileUnknown + case fileWebp + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .fileGif: + if boxed { + buffer.appendInt32(-891180321) } - if Int(flags) & Int(1 << 3) != 0 {serializeString(software!, buffer: buffer, boxed: false)} - return (FunctionDescription(name: "stickers.createStickerSet", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("title", String(describing: title)), ("shortName", String(describing: shortName)), ("thumb", String(describing: thumb)), ("stickers", String(describing: stickers)), ("software", String(describing: software))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } + + break + case .fileJpeg: + if boxed { + buffer.appendInt32(8322574) + } + + break + case .fileMov: + if boxed { + buffer.appendInt32(1258941372) + } + + break + case .fileMp3: + if boxed { + buffer.appendInt32(1384777335) + } + + break + case .fileMp4: + if boxed { + buffer.appendInt32(-1278304028) + } + + break + case .filePartial: + if boxed { + buffer.appendInt32(1086091090) + } + + break + case .filePdf: + if boxed { + buffer.appendInt32(-1373745011) + } + + break + case .filePng: + if boxed { + buffer.appendInt32(172975040) + } + + break + case .fileUnknown: + if boxed { + buffer.appendInt32(-1432995067) + } + + break + case .fileWebp: + if boxed { + buffer.appendInt32(276907596) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .fileGif: + return ("fileGif", []) + case .fileJpeg: + return ("fileJpeg", []) + case .fileMov: + return ("fileMov", []) + case .fileMp3: + return ("fileMp3", []) + case .fileMp4: + return ("fileMp4", []) + case .filePartial: + return ("filePartial", []) + case .filePdf: + return ("filePdf", []) + case .filePng: + return ("filePng", []) + case .fileUnknown: + return ("fileUnknown", []) + case .fileWebp: + return ("fileWebp", []) + } + } + + public static func parse_fileGif(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileGif + } + public static func parse_fileJpeg(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileJpeg + } + public static func parse_fileMov(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileMov + } + public static func parse_fileMp3(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileMp3 + } + public static func parse_fileMp4(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileMp4 + } + public static func parse_filePartial(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.filePartial + } + public static func parse_filePdf(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.filePdf + } + public static func parse_filePng(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.filePng + } + public static func parse_fileUnknown(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileUnknown + } + public static func parse_fileWebp(_ reader: BufferReader) -> FileType? { + return Api.storage.FileType.fileWebp + } + + } } -public extension Api.functions.stickers { - static func removeStickerFromSet(sticker: Api.InputDocument) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-143257775) - sticker.serialize(buffer, true) - return (FunctionDescription(name: "stickers.removeStickerFromSet", parameters: [("sticker", String(describing: sticker))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } -} -public extension Api.functions.stickers { - static func setStickerSetThumb(stickerset: Api.InputStickerSet, thumb: Api.InputDocument) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1707717072) - stickerset.serialize(buffer, true) - thumb.serialize(buffer, true) - return (FunctionDescription(name: "stickers.setStickerSetThumb", parameters: [("stickerset", String(describing: stickerset)), ("thumb", String(describing: thumb))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in - let reader = BufferReader(buffer) - var result: Api.messages.StickerSet? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet - } - return result - }) - } -} -public extension Api.functions.stickers { - static func suggestShortName(title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(1303364867) - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "stickers.suggestShortName", parameters: [("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stickers.SuggestedShortName? in - let reader = BufferReader(buffer) - var result: Api.stickers.SuggestedShortName? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.stickers.SuggestedShortName - } - return result - }) - } -} -public extension Api.functions.updates { - static func getChannelDifference(flags: Int32, channel: Api.InputChannel, filter: Api.ChannelMessagesFilter, pts: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(51854712) - serializeInt32(flags, buffer: buffer, boxed: false) - channel.serialize(buffer, true) - filter.serialize(buffer, true) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "updates.getChannelDifference", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("filter", String(describing: filter)), ("pts", String(describing: pts)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.ChannelDifference? in - let reader = BufferReader(buffer) - var result: Api.updates.ChannelDifference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.updates.ChannelDifference - } - return result - }) - } -} -public extension Api.functions.updates { - static func getDifference(flags: Int32, pts: Int32, ptsTotalLimit: Int32?, date: Int32, qts: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(630429265) +public extension Api.updates { + enum ChannelDifference: TypeConstructorDescription { + case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User]) + case channelDifferenceEmpty(flags: Int32, pts: Int32, timeout: Int32?) + case channelDifferenceTooLong(flags: Int32, timeout: Int32?, dialog: Api.Dialog, messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): + if boxed { + buffer.appendInt32(543450958) + } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(pts, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ptsTotalLimit!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newMessages.count)) + for item in newMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUpdates.count)) + for item in otherUpdates { + item.serialize(buffer, true) + } + 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 + case .channelDifferenceEmpty(let flags, let pts, let timeout): + if boxed { + buffer.appendInt32(1041346555) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + break + case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): + if boxed { + buffer.appendInt32(-1531132162) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(timeout!, buffer: buffer, boxed: false)} + dialog.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messages.count)) + for item in messages { + item.serialize(buffer, true) + } + 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 .channelDifference(let flags, let pts, let timeout, let newMessages, let otherUpdates, let chats, let users): + return ("channelDifference", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("timeout", String(describing: timeout)), ("newMessages", String(describing: newMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + case .channelDifferenceEmpty(let flags, let pts, let timeout): + return ("channelDifferenceEmpty", [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("timeout", String(describing: timeout))]) + case .channelDifferenceTooLong(let flags, let timeout, let dialog, let messages, let chats, let users): + return ("channelDifferenceTooLong", [("flags", String(describing: flags)), ("timeout", String(describing: timeout)), ("dialog", String(describing: dialog)), ("messages", String(describing: messages)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_channelDifference(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + var _4: [Api.Message]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _5: [Api.Update]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _6: [Api.Chat]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.updates.ChannelDifference.channelDifference(flags: _1!, pts: _2!, timeout: _3, newMessages: _4!, otherUpdates: _5!, chats: _6!, users: _7!) + } + else { + return nil + } + } + public static func parse_channelDifferenceEmpty(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil + if _c1 && _c2 && _c3 { + return Api.updates.ChannelDifference.channelDifferenceEmpty(flags: _1!, pts: _2!, timeout: _3) + } + else { + return nil + } + } + public static func parse_channelDifferenceTooLong(_ reader: BufferReader) -> ChannelDifference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 1) != 0 {_2 = reader.readInt32() } + var _3: Api.Dialog? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Dialog + } + var _4: [Api.Message]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + 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 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.updates.ChannelDifference.channelDifferenceTooLong(flags: _1!, timeout: _2, dialog: _3!, messages: _4!, chats: _5!, users: _6!) + } + else { + return nil + } + } + + } +} +public extension Api.updates { + enum Difference: TypeConstructorDescription { + case difference(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], state: Api.updates.State) + case differenceEmpty(date: Int32, seq: Int32) + case differenceSlice(newMessages: [Api.Message], newEncryptedMessages: [Api.EncryptedMessage], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User], intermediateState: Api.updates.State) + case differenceTooLong(pts: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .difference(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let state): + if boxed { + buffer.appendInt32(16030880) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newMessages.count)) + for item in newMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newEncryptedMessages.count)) + for item in newEncryptedMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUpdates.count)) + for item in otherUpdates { + item.serialize(buffer, true) + } + 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) + } + state.serialize(buffer, true) + break + case .differenceEmpty(let date, let seq): + if boxed { + buffer.appendInt32(1567990072) + } serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(seq, buffer: buffer, boxed: false) + break + case .differenceSlice(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let intermediateState): + if boxed { + buffer.appendInt32(-1459938943) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newMessages.count)) + for item in newMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(newEncryptedMessages.count)) + for item in newEncryptedMessages { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUpdates.count)) + for item in otherUpdates { + item.serialize(buffer, true) + } + 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) + } + intermediateState.serialize(buffer, true) + break + case .differenceTooLong(let pts): + if boxed { + buffer.appendInt32(1258196845) + } + serializeInt32(pts, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .difference(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let state): + return ("difference", [("newMessages", String(describing: newMessages)), ("newEncryptedMessages", String(describing: newEncryptedMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("state", String(describing: state))]) + case .differenceEmpty(let date, let seq): + return ("differenceEmpty", [("date", String(describing: date)), ("seq", String(describing: seq))]) + case .differenceSlice(let newMessages, let newEncryptedMessages, let otherUpdates, let chats, let users, let intermediateState): + return ("differenceSlice", [("newMessages", String(describing: newMessages)), ("newEncryptedMessages", String(describing: newEncryptedMessages)), ("otherUpdates", String(describing: otherUpdates)), ("chats", String(describing: chats)), ("users", String(describing: users)), ("intermediateState", String(describing: intermediateState))]) + case .differenceTooLong(let pts): + return ("differenceTooLong", [("pts", String(describing: pts))]) + } + } + + public static func parse_difference(_ reader: BufferReader) -> Difference? { + var _1: [Api.Message]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _2: [Api.EncryptedMessage]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.EncryptedMessage.self) + } + var _3: [Api.Update]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _4: [Api.Chat]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _5: [Api.User]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _6: Api.updates.State? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.updates.State + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.updates.Difference.difference(newMessages: _1!, newEncryptedMessages: _2!, otherUpdates: _3!, chats: _4!, users: _5!, state: _6!) + } + else { + return nil + } + } + public static func parse_differenceEmpty(_ reader: BufferReader) -> Difference? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.updates.Difference.differenceEmpty(date: _1!, seq: _2!) + } + else { + return nil + } + } + public static func parse_differenceSlice(_ reader: BufferReader) -> Difference? { + var _1: [Api.Message]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self) + } + var _2: [Api.EncryptedMessage]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.EncryptedMessage.self) + } + var _3: [Api.Update]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Update.self) + } + var _4: [Api.Chat]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _5: [Api.User]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + var _6: Api.updates.State? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.updates.State + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.updates.Difference.differenceSlice(newMessages: _1!, newEncryptedMessages: _2!, otherUpdates: _3!, chats: _4!, users: _5!, intermediateState: _6!) + } + else { + return nil + } + } + public static func parse_differenceTooLong(_ reader: BufferReader) -> Difference? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.updates.Difference.differenceTooLong(pts: _1!) + } + else { + return nil + } + } + + } +} +public extension Api.updates { + enum State: TypeConstructorDescription { + case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .state(let pts, let qts, let date, let seq, let unreadCount): + if boxed { + buffer.appendInt32(-1519637954) + } + serializeInt32(pts, buffer: buffer, boxed: false) serializeInt32(qts, buffer: buffer, boxed: false) - return (FunctionDescription(name: "updates.getDifference", parameters: [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("ptsTotalLimit", String(describing: ptsTotalLimit)), ("date", String(describing: date)), ("qts", String(describing: qts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.Difference? in - let reader = BufferReader(buffer) - var result: Api.updates.Difference? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.updates.Difference - } - return result - }) - } + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(seq, buffer: buffer, boxed: false) + serializeInt32(unreadCount, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .state(let pts, let qts, let date, let seq, let unreadCount): + return ("state", [("pts", String(describing: pts)), ("qts", String(describing: qts)), ("date", String(describing: date)), ("seq", String(describing: seq)), ("unreadCount", String(describing: unreadCount))]) + } + } + + public static func parse_state(_ reader: BufferReader) -> State? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!) + } + else { + return nil + } + } + + } } -public extension Api.functions.updates { - static func getState() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-304838614) - - return (FunctionDescription(name: "updates.getState", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.State? in - let reader = BufferReader(buffer) - var result: Api.updates.State? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.updates.State - } - return result - }) - } -} -public extension Api.functions.upload { - static func getCdnFile(fileToken: Buffer, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(962554330) - serializeBytes(fileToken, buffer: buffer, boxed: false) - serializeInt64(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.getCdnFile", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.CdnFile? in - let reader = BufferReader(buffer) - var result: Api.upload.CdnFile? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.upload.CdnFile - } - return result - }) - } -} -public extension Api.functions.upload { - static func getCdnFileHashes(fileToken: Buffer, offset: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { - let buffer = Buffer() - buffer.appendInt32(-1847836879) - serializeBytes(fileToken, buffer: buffer, boxed: false) - serializeInt64(offset, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.getCdnFileHashes", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in - let reader = BufferReader(buffer) - var result: [Api.FileHash]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) - } - return result - }) - } -} -public extension Api.functions.upload { - static func getFile(flags: Int32, location: Api.InputFileLocation, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1101843010) - serializeInt32(flags, buffer: buffer, boxed: false) - location.serialize(buffer, true) - serializeInt64(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.getFile", parameters: [("flags", String(describing: flags)), ("location", String(describing: location)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.File? in - let reader = BufferReader(buffer) - var result: Api.upload.File? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.upload.File - } - return result - }) - } -} -public extension Api.functions.upload { - static func getFileHashes(location: Api.InputFileLocation, offset: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { - let buffer = Buffer() - buffer.appendInt32(-1856595926) - location.serialize(buffer, true) - serializeInt64(offset, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.getFileHashes", parameters: [("location", String(describing: location)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in - let reader = BufferReader(buffer) - var result: [Api.FileHash]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) - } - return result - }) - } -} -public extension Api.functions.upload { - static func getWebFile(location: Api.InputWebFileLocation, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(619086221) - location.serialize(buffer, true) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.getWebFile", parameters: [("location", String(describing: location)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.WebFile? in - let reader = BufferReader(buffer) - var result: Api.upload.WebFile? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.upload.WebFile - } - return result - }) - } -} -public extension Api.functions.upload { - static func reuploadCdnFile(fileToken: Buffer, requestToken: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { - let buffer = Buffer() - buffer.appendInt32(-1691921240) - serializeBytes(fileToken, buffer: buffer, boxed: false) +public extension Api.upload { + enum CdnFile: TypeConstructorDescription { + case cdnFile(bytes: Buffer) + case cdnFileReuploadNeeded(requestToken: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .cdnFile(let bytes): + if boxed { + buffer.appendInt32(-1449145777) + } + serializeBytes(bytes, buffer: buffer, boxed: false) + break + case .cdnFileReuploadNeeded(let requestToken): + if boxed { + buffer.appendInt32(-290921362) + } serializeBytes(requestToken, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.reuploadCdnFile", parameters: [("fileToken", String(describing: fileToken)), ("requestToken", String(describing: requestToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in - let reader = BufferReader(buffer) - var result: [Api.FileHash]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .cdnFile(let bytes): + return ("cdnFile", [("bytes", String(describing: bytes))]) + case .cdnFileReuploadNeeded(let requestToken): + return ("cdnFileReuploadNeeded", [("requestToken", String(describing: requestToken))]) + } + } + + public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.upload.CdnFile.cdnFile(bytes: _1!) + } + else { + return nil + } + } + public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!) + } + else { + return nil + } + } + + } } -public extension Api.functions.upload { - static func saveBigFilePart(fileId: Int64, filePart: Int32, fileTotalParts: Int32, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-562337987) - serializeInt64(fileId, buffer: buffer, boxed: false) - serializeInt32(filePart, buffer: buffer, boxed: false) - serializeInt32(fileTotalParts, buffer: buffer, boxed: false) +public extension Api.upload { + enum File: TypeConstructorDescription { + case file(type: Api.storage.FileType, mtime: Int32, bytes: Buffer) + case fileCdnRedirect(dcId: Int32, fileToken: Buffer, encryptionKey: Buffer, encryptionIv: Buffer, fileHashes: [Api.FileHash]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .file(let type, let mtime, let bytes): + if boxed { + buffer.appendInt32(157948117) + } + type.serialize(buffer, true) + serializeInt32(mtime, buffer: buffer, boxed: false) serializeBytes(bytes, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.saveBigFilePart", parameters: [("fileId", String(describing: fileId)), ("filePart", String(describing: filePart)), ("fileTotalParts", String(describing: fileTotalParts)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.upload { - static func saveFilePart(fileId: Int64, filePart: Int32, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1291540959) - serializeInt64(fileId, buffer: buffer, boxed: false) - serializeInt32(filePart, buffer: buffer, boxed: false) - serializeBytes(bytes, buffer: buffer, boxed: false) - return (FunctionDescription(name: "upload.saveFilePart", parameters: [("fileId", String(describing: fileId)), ("filePart", String(describing: filePart)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } -} -public extension Api.functions.users { - static func getFullUser(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1240508136) - id.serialize(buffer, true) - return (FunctionDescription(name: "users.getFullUser", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.users.UserFull? in - let reader = BufferReader(buffer) - var result: Api.users.UserFull? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.users.UserFull - } - return result - }) - } -} -public extension Api.functions.users { - static func getUsers(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.User]>) { - let buffer = Buffer() - buffer.appendInt32(227648840) + break + case .fileCdnRedirect(let dcId, let fileToken, let encryptionKey, let encryptionIv, let fileHashes): + if boxed { + buffer.appendInt32(-242427324) + } + serializeInt32(dcId, buffer: buffer, boxed: false) + serializeBytes(fileToken, buffer: buffer, boxed: false) + serializeBytes(encryptionKey, buffer: buffer, boxed: false) + serializeBytes(encryptionIv, buffer: buffer, boxed: false) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(id.count)) - for item in id { + buffer.appendInt32(Int32(fileHashes.count)) + for item in fileHashes { item.serialize(buffer, true) } - return (FunctionDescription(name: "users.getUsers", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.User]? in - let reader = BufferReader(buffer) - var result: [Api.User]? - if let _ = reader.readInt32() { - result = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - return result - }) - } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .file(let type, let mtime, let bytes): + return ("file", [("type", String(describing: type)), ("mtime", String(describing: mtime)), ("bytes", String(describing: bytes))]) + case .fileCdnRedirect(let dcId, let fileToken, let encryptionKey, let encryptionIv, let fileHashes): + return ("fileCdnRedirect", [("dcId", String(describing: dcId)), ("fileToken", String(describing: fileToken)), ("encryptionKey", String(describing: encryptionKey)), ("encryptionIv", String(describing: encryptionIv)), ("fileHashes", String(describing: fileHashes))]) + } + } + + public static func parse_file(_ reader: BufferReader) -> File? { + var _1: Api.storage.FileType? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.storage.FileType + } + var _2: Int32? + _2 = reader.readInt32() + var _3: Buffer? + _3 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.upload.File.file(type: _1!, mtime: _2!, bytes: _3!) + } + else { + return nil + } + } + public static func parse_fileCdnRedirect(_ reader: BufferReader) -> File? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Buffer? + _2 = parseBytes(reader) + var _3: Buffer? + _3 = parseBytes(reader) + var _4: Buffer? + _4 = parseBytes(reader) + var _5: [Api.FileHash]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.upload.File.fileCdnRedirect(dcId: _1!, fileToken: _2!, encryptionKey: _3!, encryptionIv: _4!, fileHashes: _5!) + } + else { + return nil + } + } + + } } -public extension Api.functions.users { - static func setSecureValueErrors(id: Api.InputUser, errors: [Api.SecureValueError]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-1865902923) - id.serialize(buffer, true) +public extension Api.upload { + enum WebFile: TypeConstructorDescription { + case webFile(size: Int32, mimeType: String, fileType: Api.storage.FileType, mtime: Int32, bytes: Buffer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .webFile(let size, let mimeType, let fileType, let mtime, let bytes): + if boxed { + buffer.appendInt32(568808380) + } + serializeInt32(size, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + fileType.serialize(buffer, true) + serializeInt32(mtime, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .webFile(let size, let mimeType, let fileType, let mtime, let bytes): + return ("webFile", [("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("fileType", String(describing: fileType)), ("mtime", String(describing: mtime)), ("bytes", String(describing: bytes))]) + } + } + + public static func parse_webFile(_ reader: BufferReader) -> WebFile? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: Api.storage.FileType? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.storage.FileType + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Buffer? + _5 = parseBytes(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.upload.WebFile.webFile(size: _1!, mimeType: _2!, fileType: _3!, mtime: _4!, bytes: _5!) + } + else { + return nil + } + } + + } +} +public extension Api.users { + enum UserFull: TypeConstructorDescription { + case userFull(fullUser: Api.UserFull, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .userFull(let fullUser, let chats, let users): + if boxed { + buffer.appendInt32(997004590) + } + fullUser.serialize(buffer, true) buffer.appendInt32(481674261) - buffer.appendInt32(Int32(errors.count)) - for item in errors { + buffer.appendInt32(Int32(chats.count)) + for item in chats { item.serialize(buffer, true) } - return (FunctionDescription(name: "users.setSecureValueErrors", parameters: [("id", String(describing: id)), ("errors", String(describing: errors))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in - let reader = BufferReader(buffer) - var result: Api.Bool? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Bool - } - return result - }) - } + 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 .userFull(let fullUser, let chats, let users): + return ("userFull", [("fullUser", String(describing: fullUser)), ("chats", String(describing: chats)), ("users", String(describing: users))]) + } + } + + public static func parse_userFull(_ reader: BufferReader) -> UserFull? { + var _1: Api.UserFull? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.UserFull + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.users.UserFull.userFull(fullUser: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } } diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift new file mode 100644 index 0000000000..220dbe1deb --- /dev/null +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -0,0 +1,7525 @@ +public extension Api.functions.account { + static func acceptAuthorization(botId: Int64, scope: String, publicKey: String, valueHashes: [Api.SecureValueHash], credentials: Api.SecureCredentialsEncrypted) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-202552205) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeString(scope, buffer: buffer, boxed: false) + serializeString(publicKey, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(valueHashes.count)) + for item in valueHashes { + item.serialize(buffer, true) + } + credentials.serialize(buffer, true) + return (FunctionDescription(name: "account.acceptAuthorization", parameters: [("botId", String(describing: botId)), ("scope", String(describing: scope)), ("publicKey", String(describing: publicKey)), ("valueHashes", String(describing: valueHashes)), ("credentials", String(describing: credentials))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func cancelPasswordEmail() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1043606090) + + return (FunctionDescription(name: "account.cancelPasswordEmail", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func changeAuthorizationSettings(flags: Int32, hash: Int64, encryptedRequestsDisabled: Api.Bool?, callRequestsDisabled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1089766498) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {encryptedRequestsDisabled!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {callRequestsDisabled!.serialize(buffer, true)} + return (FunctionDescription(name: "account.changeAuthorizationSettings", parameters: [("flags", String(describing: flags)), ("hash", String(describing: hash)), ("encryptedRequestsDisabled", String(describing: encryptedRequestsDisabled)), ("callRequestsDisabled", String(describing: callRequestsDisabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func changePhone(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1891839707) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeString(phoneCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.changePhone", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in + let reader = BufferReader(buffer) + var result: Api.User? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.User + } + return result + }) + } +} +public extension Api.functions.account { + static func checkUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(655677548) + serializeString(username, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.checkUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func confirmPasswordEmail(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1881204448) + serializeString(code, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.confirmPasswordEmail", parameters: [("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func confirmPhone(phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1596029123) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeString(phoneCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.confirmPhone", parameters: [("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func createTheme(flags: Int32, slug: String, title: String, document: Api.InputDocument?, settings: [Api.InputThemeSettings]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1697530880) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(slug, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(settings!.count)) + for item in settings! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "account.createTheme", parameters: [("flags", String(describing: flags)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in + let reader = BufferReader(buffer) + var result: Api.Theme? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Theme + } + return result + }) + } +} +public extension Api.functions.account { + static func declinePasswordReset() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1284770294) + + return (FunctionDescription(name: "account.declinePasswordReset", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func deleteAccount(flags: Int32, reason: String, password: Api.InputCheckPasswordSRP?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1564422284) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(reason, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {password!.serialize(buffer, true)} + return (FunctionDescription(name: "account.deleteAccount", parameters: [("flags", String(describing: flags)), ("reason", String(describing: reason)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func deleteSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1199522741) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(types.count)) + for item in types { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "account.deleteSecureValue", parameters: [("types", String(describing: types))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func finishTakeoutSession(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(489050862) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.finishTakeoutSession", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func getAccountTTL() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(150761757) + + return (FunctionDescription(name: "account.getAccountTTL", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AccountDaysTTL? in + let reader = BufferReader(buffer) + var result: Api.AccountDaysTTL? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.AccountDaysTTL + } + return result + }) + } +} +public extension Api.functions.account { + static func getAllSecureValues() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SecureValue]>) { + let buffer = Buffer() + buffer.appendInt32(-1299661699) + + return (FunctionDescription(name: "account.getAllSecureValues", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SecureValue]? in + let reader = BufferReader(buffer) + var result: [Api.SecureValue]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) + } + return result + }) + } +} +public extension Api.functions.account { + static func getAuthorizationForm(botId: Int64, scope: String, publicKey: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1456907910) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeString(scope, buffer: buffer, boxed: false) + serializeString(publicKey, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getAuthorizationForm", parameters: [("botId", String(describing: botId)), ("scope", String(describing: scope)), ("publicKey", String(describing: publicKey))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.AuthorizationForm? in + let reader = BufferReader(buffer) + var result: Api.account.AuthorizationForm? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.AuthorizationForm + } + return result + }) + } +} +public extension Api.functions.account { + static func getAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-484392616) + + return (FunctionDescription(name: "account.getAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Authorizations? in + let reader = BufferReader(buffer) + var result: Api.account.Authorizations? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.Authorizations + } + return result + }) + } +} +public extension Api.functions.account { + static func getAutoDownloadSettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1457130303) + + return (FunctionDescription(name: "account.getAutoDownloadSettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.AutoDownloadSettings? in + let reader = BufferReader(buffer) + var result: Api.account.AutoDownloadSettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.AutoDownloadSettings + } + return result + }) + } +} +public extension Api.functions.account { + static func getChatThemes(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-700916087) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getChatThemes", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Themes? in + let reader = BufferReader(buffer) + var result: Api.account.Themes? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.Themes + } + return result + }) + } +} +public extension Api.functions.account { + static func getContactSignUpNotification() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1626880216) + + return (FunctionDescription(name: "account.getContactSignUpNotification", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func getContentSettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1952756306) + + return (FunctionDescription(name: "account.getContentSettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.ContentSettings? in + let reader = BufferReader(buffer) + var result: Api.account.ContentSettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.ContentSettings + } + return result + }) + } +} +public extension Api.functions.account { + static func getGlobalPrivacySettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-349483786) + + return (FunctionDescription(name: "account.getGlobalPrivacySettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.GlobalPrivacySettings? in + let reader = BufferReader(buffer) + var result: Api.GlobalPrivacySettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.GlobalPrivacySettings + } + return result + }) + } +} +public extension Api.functions.account { + static func getMultiWallPapers(wallpapers: [Api.InputWallPaper]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.WallPaper]>) { + let buffer = Buffer() + buffer.appendInt32(1705865692) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(wallpapers.count)) + for item in wallpapers { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "account.getMultiWallPapers", parameters: [("wallpapers", String(describing: wallpapers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.WallPaper]? in + let reader = BufferReader(buffer) + var result: [Api.WallPaper]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.WallPaper.self) + } + return result + }) + } +} +public extension Api.functions.account { + static func getNotifyExceptions(flags: Int32, peer: Api.InputNotifyPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1398240377) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)} + return (FunctionDescription(name: "account.getNotifyExceptions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.account { + static func getNotifySettings(peer: Api.InputNotifyPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(313765169) + peer.serialize(buffer, true) + return (FunctionDescription(name: "account.getNotifySettings", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.PeerNotifySettings? in + let reader = BufferReader(buffer) + var result: Api.PeerNotifySettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings + } + return result + }) + } +} +public extension Api.functions.account { + static func getPassword() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1418342645) + + return (FunctionDescription(name: "account.getPassword", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Password? in + let reader = BufferReader(buffer) + var result: Api.account.Password? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.Password + } + return result + }) + } +} +public extension Api.functions.account { + static func getPasswordSettings(password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1663767815) + password.serialize(buffer, true) + return (FunctionDescription(name: "account.getPasswordSettings", parameters: [("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PasswordSettings? in + let reader = BufferReader(buffer) + var result: Api.account.PasswordSettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.PasswordSettings + } + return result + }) + } +} +public extension Api.functions.account { + static func getPrivacy(key: Api.InputPrivacyKey) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-623130288) + key.serialize(buffer, true) + return (FunctionDescription(name: "account.getPrivacy", parameters: [("key", String(describing: key))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PrivacyRules? in + let reader = BufferReader(buffer) + var result: Api.account.PrivacyRules? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.PrivacyRules + } + return result + }) + } +} +public extension Api.functions.account { + static func getSavedRingtones(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-510647672) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getSavedRingtones", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtones? in + let reader = BufferReader(buffer) + var result: Api.account.SavedRingtones? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtones + } + return result + }) + } +} +public extension Api.functions.account { + static func getSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SecureValue]>) { + let buffer = Buffer() + buffer.appendInt32(1936088002) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(types.count)) + for item in types { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "account.getSecureValue", parameters: [("types", String(describing: types))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SecureValue]? in + let reader = BufferReader(buffer) + var result: [Api.SecureValue]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SecureValue.self) + } + return result + }) + } +} +public extension Api.functions.account { + static func getTheme(format: String, theme: Api.InputTheme, documentId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1919060949) + serializeString(format, buffer: buffer, boxed: false) + theme.serialize(buffer, true) + serializeInt64(documentId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getTheme", parameters: [("format", String(describing: format)), ("theme", String(describing: theme)), ("documentId", String(describing: documentId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in + let reader = BufferReader(buffer) + var result: Api.Theme? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Theme + } + return result + }) + } +} +public extension Api.functions.account { + static func getThemes(format: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1913054296) + serializeString(format, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getThemes", parameters: [("format", String(describing: format)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Themes? in + let reader = BufferReader(buffer) + var result: Api.account.Themes? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.Themes + } + return result + }) + } +} +public extension Api.functions.account { + static func getTmpPassword(password: Api.InputCheckPasswordSRP, period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1151208273) + password.serialize(buffer, true) + serializeInt32(period, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getTmpPassword", parameters: [("password", String(describing: password)), ("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.TmpPassword? in + let reader = BufferReader(buffer) + var result: Api.account.TmpPassword? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.TmpPassword + } + return result + }) + } +} +public extension Api.functions.account { + static func getWallPaper(wallpaper: Api.InputWallPaper) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-57811990) + wallpaper.serialize(buffer, true) + return (FunctionDescription(name: "account.getWallPaper", parameters: [("wallpaper", String(describing: wallpaper))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WallPaper? in + let reader = BufferReader(buffer) + var result: Api.WallPaper? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.WallPaper + } + return result + }) + } +} +public extension Api.functions.account { + static func getWallPapers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(127302966) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.getWallPapers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.WallPapers? in + let reader = BufferReader(buffer) + var result: Api.account.WallPapers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.WallPapers + } + return result + }) + } +} +public extension Api.functions.account { + static func getWebAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(405695855) + + return (FunctionDescription(name: "account.getWebAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.WebAuthorizations? in + let reader = BufferReader(buffer) + var result: Api.account.WebAuthorizations? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.WebAuthorizations + } + return result + }) + } +} +public extension Api.functions.account { + static func initTakeoutSession(flags: Int32, fileMaxSize: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1896617296) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 5) != 0 {serializeInt64(fileMaxSize!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "account.initTakeoutSession", parameters: [("flags", String(describing: flags)), ("fileMaxSize", String(describing: fileMaxSize))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Takeout? in + let reader = BufferReader(buffer) + var result: Api.account.Takeout? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.Takeout + } + return result + }) + } +} +public extension Api.functions.account { + static func installTheme(flags: Int32, theme: Api.InputTheme?, format: String?, baseTheme: Api.BaseTheme?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-953697477) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {theme!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(format!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {baseTheme!.serialize(buffer, true)} + return (FunctionDescription(name: "account.installTheme", parameters: [("flags", String(describing: flags)), ("theme", String(describing: theme)), ("format", String(describing: format)), ("baseTheme", String(describing: baseTheme))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func installWallPaper(wallpaper: Api.InputWallPaper, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-18000023) + wallpaper.serialize(buffer, true) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.installWallPaper", parameters: [("wallpaper", String(describing: wallpaper)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func registerDevice(flags: Int32, tokenType: Int32, token: String, appSandbox: Api.Bool, secret: Buffer, otherUids: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-326762118) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(tokenType, buffer: buffer, boxed: false) + serializeString(token, buffer: buffer, boxed: false) + appSandbox.serialize(buffer, true) + serializeBytes(secret, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUids.count)) + for item in otherUids { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "account.registerDevice", parameters: [("flags", String(describing: flags)), ("tokenType", String(describing: tokenType)), ("token", String(describing: token)), ("appSandbox", String(describing: appSandbox)), ("secret", String(describing: secret)), ("otherUids", String(describing: otherUids))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func reportPeer(peer: Api.InputPeer, reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-977650298) + peer.serialize(buffer, true) + reason.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.reportPeer", parameters: [("peer", String(describing: peer)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func reportProfilePhoto(peer: Api.InputPeer, photoId: Api.InputPhoto, reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-91437323) + peer.serialize(buffer, true) + photoId.serialize(buffer, true) + reason.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.reportProfilePhoto", parameters: [("peer", String(describing: peer)), ("photoId", String(describing: photoId)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resendPasswordEmail() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2055154197) + + return (FunctionDescription(name: "account.resendPasswordEmail", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resetAuthorization(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-545786948) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.resetAuthorization", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resetNotifySettings() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-612493497) + + return (FunctionDescription(name: "account.resetNotifySettings", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resetPassword() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1828139493) + + return (FunctionDescription(name: "account.resetPassword", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.ResetPasswordResult? in + let reader = BufferReader(buffer) + var result: Api.account.ResetPasswordResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.ResetPasswordResult + } + return result + }) + } +} +public extension Api.functions.account { + static func resetWallPapers() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1153722364) + + return (FunctionDescription(name: "account.resetWallPapers", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resetWebAuthorization(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(755087855) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.resetWebAuthorization", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func resetWebAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1747789204) + + return (FunctionDescription(name: "account.resetWebAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func saveAutoDownloadSettings(flags: Int32, settings: Api.AutoDownloadSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1995661875) + serializeInt32(flags, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.saveAutoDownloadSettings", parameters: [("flags", String(describing: flags)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func saveRingtone(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1038768899) + id.serialize(buffer, true) + unsave.serialize(buffer, true) + return (FunctionDescription(name: "account.saveRingtone", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SavedRingtone? in + let reader = BufferReader(buffer) + var result: Api.account.SavedRingtone? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.SavedRingtone + } + return result + }) + } +} +public extension Api.functions.account { + static func saveSecureValue(value: Api.InputSecureValue, secureSecretId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1986010339) + value.serialize(buffer, true) + serializeInt64(secureSecretId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.saveSecureValue", parameters: [("value", String(describing: value)), ("secureSecretId", String(describing: secureSecretId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SecureValue? in + let reader = BufferReader(buffer) + var result: Api.SecureValue? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.SecureValue + } + return result + }) + } +} +public extension Api.functions.account { + static func saveTheme(theme: Api.InputTheme, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-229175188) + theme.serialize(buffer, true) + unsave.serialize(buffer, true) + return (FunctionDescription(name: "account.saveTheme", parameters: [("theme", String(describing: theme)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func saveWallPaper(wallpaper: Api.InputWallPaper, unsave: Api.Bool, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1817860919) + wallpaper.serialize(buffer, true) + unsave.serialize(buffer, true) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.saveWallPaper", parameters: [("wallpaper", String(describing: wallpaper)), ("unsave", String(describing: unsave)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func sendChangePhoneCode(phoneNumber: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2108208411) + serializeString(phoneNumber, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.sendChangePhoneCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} +public extension Api.functions.account { + static func sendConfirmPhoneCode(hash: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(457157256) + serializeString(hash, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.sendConfirmPhoneCode", parameters: [("hash", String(describing: hash)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} +public extension Api.functions.account { + static func sendVerifyEmailCode(email: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1880182943) + serializeString(email, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.sendVerifyEmailCode", parameters: [("email", String(describing: email))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.SentEmailCode? in + let reader = BufferReader(buffer) + var result: Api.account.SentEmailCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.SentEmailCode + } + return result + }) + } +} +public extension Api.functions.account { + static func sendVerifyPhoneCode(phoneNumber: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1516022023) + serializeString(phoneNumber, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.sendVerifyPhoneCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} +public extension Api.functions.account { + static func setAccountTTL(ttl: Api.AccountDaysTTL) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(608323678) + ttl.serialize(buffer, true) + return (FunctionDescription(name: "account.setAccountTTL", parameters: [("ttl", String(describing: ttl))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func setAuthorizationTTL(authorizationTtlDays: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1081501024) + serializeInt32(authorizationTtlDays, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.setAuthorizationTTL", parameters: [("authorizationTtlDays", String(describing: authorizationTtlDays))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func setContactSignUpNotification(silent: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-806076575) + silent.serialize(buffer, true) + return (FunctionDescription(name: "account.setContactSignUpNotification", parameters: [("silent", String(describing: silent))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func setContentSettings(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1250643605) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.setContentSettings", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func setGlobalPrivacySettings(settings: Api.GlobalPrivacySettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(517647042) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.setGlobalPrivacySettings", parameters: [("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.GlobalPrivacySettings? in + let reader = BufferReader(buffer) + var result: Api.GlobalPrivacySettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.GlobalPrivacySettings + } + return result + }) + } +} +public extension Api.functions.account { + static func setPrivacy(key: Api.InputPrivacyKey, rules: [Api.InputPrivacyRule]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-906486552) + key.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(rules.count)) + for item in rules { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "account.setPrivacy", parameters: [("key", String(describing: key)), ("rules", String(describing: rules))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PrivacyRules? in + let reader = BufferReader(buffer) + var result: Api.account.PrivacyRules? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.account.PrivacyRules + } + return result + }) + } +} +public extension Api.functions.account { + static func unregisterDevice(tokenType: Int32, token: String, otherUids: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1779249670) + serializeInt32(tokenType, buffer: buffer, boxed: false) + serializeString(token, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUids.count)) + for item in otherUids { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "account.unregisterDevice", parameters: [("tokenType", String(describing: tokenType)), ("token", String(describing: token)), ("otherUids", String(describing: otherUids))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func updateDeviceLocked(period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(954152242) + serializeInt32(period, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.updateDeviceLocked", parameters: [("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func updateNotifySettings(peer: Api.InputNotifyPeer, settings: Api.InputPeerNotifySettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2067899501) + peer.serialize(buffer, true) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.updateNotifySettings", parameters: [("peer", String(describing: peer)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func updatePasswordSettings(password: Api.InputCheckPasswordSRP, newSettings: Api.account.PasswordInputSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1516564433) + password.serialize(buffer, true) + newSettings.serialize(buffer, true) + return (FunctionDescription(name: "account.updatePasswordSettings", parameters: [("password", String(describing: password)), ("newSettings", String(describing: newSettings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func updateProfile(flags: Int32, firstName: String?, lastName: String?, about: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2018596725) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(firstName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(lastName!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(about!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "account.updateProfile", parameters: [("flags", String(describing: flags)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("about", String(describing: about))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in + let reader = BufferReader(buffer) + var result: Api.User? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.User + } + return result + }) + } +} +public extension Api.functions.account { + static func updateStatus(offline: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1713919532) + offline.serialize(buffer, true) + return (FunctionDescription(name: "account.updateStatus", parameters: [("offline", String(describing: offline))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func updateTheme(flags: Int32, format: String, theme: Api.InputTheme, slug: String?, title: String?, document: Api.InputDocument?, settings: [Api.InputThemeSettings]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(737414348) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(format, buffer: buffer, boxed: false) + theme.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeString(slug!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {document!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(settings!.count)) + for item in settings! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "account.updateTheme", parameters: [("flags", String(describing: flags)), ("format", String(describing: format)), ("theme", String(describing: theme)), ("slug", String(describing: slug)), ("title", String(describing: title)), ("document", String(describing: document)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Theme? in + let reader = BufferReader(buffer) + var result: Api.Theme? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Theme + } + return result + }) + } +} +public extension Api.functions.account { + static func updateUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1040964988) + serializeString(username, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.updateUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.User? in + let reader = BufferReader(buffer) + var result: Api.User? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.User + } + return result + }) + } +} +public extension Api.functions.account { + static func uploadRingtone(file: Api.InputFile, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2095414366) + file.serialize(buffer, true) + serializeString(fileName, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.uploadRingtone", parameters: [("file", String(describing: file)), ("fileName", String(describing: fileName)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in + let reader = BufferReader(buffer) + var result: Api.Document? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Document + } + return result + }) + } +} +public extension Api.functions.account { + static func uploadTheme(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, fileName: String, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(473805619) + serializeInt32(flags, buffer: buffer, boxed: false) + file.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {thumb!.serialize(buffer, true)} + serializeString(fileName, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.uploadTheme", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("thumb", String(describing: thumb)), ("fileName", String(describing: fileName)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in + let reader = BufferReader(buffer) + var result: Api.Document? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Document + } + return result + }) + } +} +public extension Api.functions.account { + static func uploadWallPaper(file: Api.InputFile, mimeType: String, settings: Api.WallPaperSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-578472351) + file.serialize(buffer, true) + serializeString(mimeType, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "account.uploadWallPaper", parameters: [("file", String(describing: file)), ("mimeType", String(describing: mimeType)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WallPaper? in + let reader = BufferReader(buffer) + var result: Api.WallPaper? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.WallPaper + } + return result + }) + } +} +public extension Api.functions.account { + static func verifyEmail(email: String, code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-323339813) + serializeString(email, buffer: buffer, boxed: false) + serializeString(code, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.verifyEmail", parameters: [("email", String(describing: email)), ("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.account { + static func verifyPhone(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1305716726) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeString(phoneCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "account.verifyPhone", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func acceptLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-392909491) + serializeBytes(token, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.acceptLoginToken", parameters: [("token", String(describing: token))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Authorization? in + let reader = BufferReader(buffer) + var result: Api.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func bindTempAuthKey(permAuthKeyId: Int64, nonce: Int64, expiresAt: Int32, encryptedMessage: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-841733627) + serializeInt64(permAuthKeyId, buffer: buffer, boxed: false) + serializeInt64(nonce, buffer: buffer, boxed: false) + serializeInt32(expiresAt, buffer: buffer, boxed: false) + serializeBytes(encryptedMessage, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.bindTempAuthKey", parameters: [("permAuthKeyId", String(describing: permAuthKeyId)), ("nonce", String(describing: nonce)), ("expiresAt", String(describing: expiresAt)), ("encryptedMessage", String(describing: encryptedMessage))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func cancelCode(phoneNumber: String, phoneCodeHash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(520357240) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.cancelCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func checkPassword(password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-779399914) + password.serialize(buffer, true) + return (FunctionDescription(name: "auth.checkPassword", parameters: [("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func checkRecoveryPassword(code: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(221691769) + serializeString(code, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.checkRecoveryPassword", parameters: [("code", String(describing: code))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func dropTempAuthKeys(exceptAuthKeys: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1907842680) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(exceptAuthKeys.count)) + for item in exceptAuthKeys { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "auth.dropTempAuthKeys", parameters: [("exceptAuthKeys", String(describing: exceptAuthKeys))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func exportAuthorization(dcId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-440401971) + serializeInt32(dcId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.exportAuthorization", parameters: [("dcId", String(describing: dcId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.ExportedAuthorization? in + let reader = BufferReader(buffer) + var result: Api.auth.ExportedAuthorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.ExportedAuthorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func exportLoginToken(apiId: Int32, apiHash: String, exceptIds: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1210022402) + serializeInt32(apiId, buffer: buffer, boxed: false) + serializeString(apiHash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(exceptIds.count)) + for item in exceptIds { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "auth.exportLoginToken", parameters: [("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("exceptIds", String(describing: exceptIds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoginToken? in + let reader = BufferReader(buffer) + var result: Api.auth.LoginToken? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.LoginToken + } + return result + }) + } +} +public extension Api.functions.auth { + static func importAuthorization(id: Int64, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1518699091) + serializeInt64(id, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.importAuthorization", parameters: [("id", String(describing: id)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func importBotAuthorization(flags: Int32, apiId: Int32, apiHash: String, botAuthToken: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1738800940) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(apiId, buffer: buffer, boxed: false) + serializeString(apiHash, buffer: buffer, boxed: false) + serializeString(botAuthToken, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.importBotAuthorization", parameters: [("flags", String(describing: flags)), ("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("botAuthToken", String(describing: botAuthToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func importLoginToken(token: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1783866140) + serializeBytes(token, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.importLoginToken", parameters: [("token", String(describing: token))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoginToken? in + let reader = BufferReader(buffer) + var result: Api.auth.LoginToken? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.LoginToken + } + return result + }) + } +} +public extension Api.functions.auth { + static func logOut() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1047706137) + + return (FunctionDescription(name: "auth.logOut", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.LoggedOut? in + let reader = BufferReader(buffer) + var result: Api.auth.LoggedOut? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.LoggedOut + } + return result + }) + } +} +public extension Api.functions.auth { + static func recoverPassword(flags: Int32, code: String, newSettings: Api.account.PasswordInputSettings?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(923364464) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(code, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {newSettings!.serialize(buffer, true)} + return (FunctionDescription(name: "auth.recoverPassword", parameters: [("flags", String(describing: flags)), ("code", String(describing: code)), ("newSettings", String(describing: newSettings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func requestPasswordRecovery() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-661144474) + + return (FunctionDescription(name: "auth.requestPasswordRecovery", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.PasswordRecovery? in + let reader = BufferReader(buffer) + var result: Api.auth.PasswordRecovery? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.PasswordRecovery + } + return result + }) + } +} +public extension Api.functions.auth { + static func resendCode(phoneNumber: String, phoneCodeHash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1056025023) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.resendCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} +public extension Api.functions.auth { + static func resetAuthorizations() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1616179942) + + return (FunctionDescription(name: "auth.resetAuthorizations", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.auth { + static func sendCode(phoneNumber: String, apiId: Int32, apiHash: String, settings: Api.CodeSettings) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1502141361) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeInt32(apiId, buffer: buffer, boxed: false) + serializeString(apiHash, buffer: buffer, boxed: false) + settings.serialize(buffer, true) + return (FunctionDescription(name: "auth.sendCode", parameters: [("phoneNumber", String(describing: phoneNumber)), ("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash)), ("settings", String(describing: settings))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.SentCode? in + let reader = BufferReader(buffer) + var result: Api.auth.SentCode? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.SentCode + } + return result + }) + } +} +public extension Api.functions.auth { + static func signIn(phoneNumber: String, phoneCodeHash: String, phoneCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1126886015) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeString(phoneCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.signIn", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("phoneCode", String(describing: phoneCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.auth { + static func signUp(phoneNumber: String, phoneCodeHash: String, firstName: String, lastName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2131827673) + serializeString(phoneNumber, buffer: buffer, boxed: false) + serializeString(phoneCodeHash, buffer: buffer, boxed: false) + serializeString(firstName, buffer: buffer, boxed: false) + serializeString(lastName, buffer: buffer, boxed: false) + return (FunctionDescription(name: "auth.signUp", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in + let reader = BufferReader(buffer) + var result: Api.auth.Authorization? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.auth.Authorization + } + return result + }) + } +} +public extension Api.functions.bots { + static func answerWebhookJSONQuery(queryId: Int64, data: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-434028723) + serializeInt64(queryId, buffer: buffer, boxed: false) + data.serialize(buffer, true) + return (FunctionDescription(name: "bots.answerWebhookJSONQuery", parameters: [("queryId", String(describing: queryId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.bots { + static func getBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.BotCommand]>) { + let buffer = Buffer() + buffer.appendInt32(-481554986) + scope.serialize(buffer, true) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "bots.getBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.BotCommand]? in + let reader = BufferReader(buffer) + var result: [Api.BotCommand]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotCommand.self) + } + return result + }) + } +} +public extension Api.functions.bots { + static func getBotMenuButton(userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1671369944) + userId.serialize(buffer, true) + return (FunctionDescription(name: "bots.getBotMenuButton", parameters: [("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.BotMenuButton? in + let reader = BufferReader(buffer) + var result: Api.BotMenuButton? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.BotMenuButton + } + return result + }) + } +} +public extension Api.functions.bots { + static func resetBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1032708345) + scope.serialize(buffer, true) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "bots.resetBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.bots { + static func sendCustomRequest(customMethod: String, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1440257555) + serializeString(customMethod, buffer: buffer, boxed: false) + params.serialize(buffer, true) + return (FunctionDescription(name: "bots.sendCustomRequest", parameters: [("customMethod", String(describing: customMethod)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.DataJSON? in + let reader = BufferReader(buffer) + var result: Api.DataJSON? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.DataJSON + } + return result + }) + } +} +public extension Api.functions.bots { + static func setBotBroadcastDefaultAdminRights(adminRights: Api.ChatAdminRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2021942497) + adminRights.serialize(buffer, true) + return (FunctionDescription(name: "bots.setBotBroadcastDefaultAdminRights", parameters: [("adminRights", String(describing: adminRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.bots { + static func setBotCommands(scope: Api.BotCommandScope, langCode: String, commands: [Api.BotCommand]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(85399130) + scope.serialize(buffer, true) + serializeString(langCode, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(commands.count)) + for item in commands { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "bots.setBotCommands", parameters: [("scope", String(describing: scope)), ("langCode", String(describing: langCode)), ("commands", String(describing: commands))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.bots { + static func setBotGroupDefaultAdminRights(adminRights: Api.ChatAdminRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1839281686) + adminRights.serialize(buffer, true) + return (FunctionDescription(name: "bots.setBotGroupDefaultAdminRights", parameters: [("adminRights", String(describing: adminRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.bots { + static func setBotMenuButton(userId: Api.InputUser, button: Api.BotMenuButton) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1157944655) + userId.serialize(buffer, true) + button.serialize(buffer, true) + return (FunctionDescription(name: "bots.setBotMenuButton", parameters: [("userId", String(describing: userId)), ("button", String(describing: button))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func checkUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(283557164) + channel.serialize(buffer, true) + serializeString(username, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.checkUsername", parameters: [("channel", String(describing: channel)), ("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func convertToGigagroup(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(187239529) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.convertToGigagroup", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func createChannel(flags: Int32, title: String, about: String, geoPoint: Api.InputGeoPoint?, address: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1029681423) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(about, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {geoPoint!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(address!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "channels.createChannel", parameters: [("flags", String(describing: flags)), ("title", String(describing: title)), ("about", String(describing: about)), ("geoPoint", String(describing: geoPoint)), ("address", String(describing: address))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func deleteChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1072619549) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.deleteChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func deleteHistory(flags: Int32, channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1683319225) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.deleteHistory", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func deleteMessages(channel: Api.InputChannel, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2067661490) + channel.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "channels.deleteMessages", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages + } + return result + }) + } +} +public extension Api.functions.channels { + static func deleteParticipantHistory(channel: Api.InputChannel, participant: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(913655003) + channel.serialize(buffer, true) + participant.serialize(buffer, true) + return (FunctionDescription(name: "channels.deleteParticipantHistory", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} +public extension Api.functions.channels { + static func editAdmin(channel: Api.InputChannel, userId: Api.InputUser, adminRights: Api.ChatAdminRights, rank: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-751007486) + channel.serialize(buffer, true) + userId.serialize(buffer, true) + adminRights.serialize(buffer, true) + serializeString(rank, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.editAdmin", parameters: [("channel", String(describing: channel)), ("userId", String(describing: userId)), ("adminRights", String(describing: adminRights)), ("rank", String(describing: rank))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func editBanned(channel: Api.InputChannel, participant: Api.InputPeer, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1763259007) + channel.serialize(buffer, true) + participant.serialize(buffer, true) + bannedRights.serialize(buffer, true) + return (FunctionDescription(name: "channels.editBanned", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant)), ("bannedRights", String(describing: bannedRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func editCreator(channel: Api.InputChannel, userId: Api.InputUser, password: Api.InputCheckPasswordSRP) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1892102881) + channel.serialize(buffer, true) + userId.serialize(buffer, true) + password.serialize(buffer, true) + return (FunctionDescription(name: "channels.editCreator", parameters: [("channel", String(describing: channel)), ("userId", String(describing: userId)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func editLocation(channel: Api.InputChannel, geoPoint: Api.InputGeoPoint, address: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1491484525) + channel.serialize(buffer, true) + geoPoint.serialize(buffer, true) + serializeString(address, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.editLocation", parameters: [("channel", String(describing: channel)), ("geoPoint", String(describing: geoPoint)), ("address", String(describing: address))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func editPhoto(channel: Api.InputChannel, photo: Api.InputChatPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-248621111) + channel.serialize(buffer, true) + photo.serialize(buffer, true) + return (FunctionDescription(name: "channels.editPhoto", parameters: [("channel", String(describing: channel)), ("photo", String(describing: photo))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func editTitle(channel: Api.InputChannel, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1450044624) + channel.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.editTitle", parameters: [("channel", String(describing: channel)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func exportMessageLink(flags: Int32, channel: Api.InputChannel, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-432034325) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.exportMessageLink", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedMessageLink? in + let reader = BufferReader(buffer) + var result: Api.ExportedMessageLink? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.ExportedMessageLink + } + return result + }) + } +} +public extension Api.functions.channels { + static func getAdminLog(flags: Int32, channel: Api.InputChannel, q: String, eventsFilter: Api.ChannelAdminLogEventsFilter?, admins: [Api.InputUser]?, maxId: Int64, minId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(870184064) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + serializeString(q, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {eventsFilter!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(admins!.count)) + for item in admins! { + item.serialize(buffer, true) + }} + serializeInt64(maxId, buffer: buffer, boxed: false) + serializeInt64(minId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.getAdminLog", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("q", String(describing: q)), ("eventsFilter", String(describing: eventsFilter)), ("admins", String(describing: admins)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.AdminLogResults? in + let reader = BufferReader(buffer) + var result: Api.channels.AdminLogResults? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.channels.AdminLogResults + } + return result + }) + } +} +public extension Api.functions.channels { + static func getAdminedPublicChannels(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-122669393) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.getAdminedPublicChannels", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.channels { + static func getChannels(id: [Api.InputChannel]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(176122811) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "channels.getChannels", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.channels { + static func getFullChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(141781513) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.getFullChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatFull? in + let reader = BufferReader(buffer) + var result: Api.messages.ChatFull? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ChatFull + } + return result + }) + } +} +public extension Api.functions.channels { + static func getGroupsForDiscussion() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-170208392) + + return (FunctionDescription(name: "channels.getGroupsForDiscussion", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.channels { + static func getInactiveChannels() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(300429806) + + return (FunctionDescription(name: "channels.getInactiveChannels", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.InactiveChats? in + let reader = BufferReader(buffer) + var result: Api.messages.InactiveChats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.InactiveChats + } + return result + }) + } +} +public extension Api.functions.channels { + static func getLeftChannels(offset: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2092831552) + serializeInt32(offset, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.getLeftChannels", parameters: [("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.channels { + static func getMessages(channel: Api.InputChannel, id: [Api.InputMessage]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1383294429) + channel.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "channels.getMessages", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.channels { + static func getParticipant(channel: Api.InputChannel, participant: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1599378234) + channel.serialize(buffer, true) + participant.serialize(buffer, true) + return (FunctionDescription(name: "channels.getParticipant", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipant? in + let reader = BufferReader(buffer) + var result: Api.channels.ChannelParticipant? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipant + } + return result + }) + } +} +public extension Api.functions.channels { + static func getParticipants(channel: Api.InputChannel, filter: Api.ChannelParticipantsFilter, offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2010044880) + channel.serialize(buffer, true) + filter.serialize(buffer, true) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.getParticipants", parameters: [("channel", String(describing: channel)), ("filter", String(describing: filter)), ("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.ChannelParticipants? in + let reader = BufferReader(buffer) + var result: Api.channels.ChannelParticipants? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipants + } + return result + }) + } +} +public extension Api.functions.channels { + static func getSendAs(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(231174382) + peer.serialize(buffer, true) + return (FunctionDescription(name: "channels.getSendAs", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.channels.SendAsPeers? in + let reader = BufferReader(buffer) + var result: Api.channels.SendAsPeers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.channels.SendAsPeers + } + return result + }) + } +} +public extension Api.functions.channels { + static func getSponsoredMessages(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-333377601) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.getSponsoredMessages", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SponsoredMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.SponsoredMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SponsoredMessages + } + return result + }) + } +} +public extension Api.functions.channels { + static func inviteToChannel(channel: Api.InputChannel, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(429865580) + channel.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "channels.inviteToChannel", parameters: [("channel", String(describing: channel)), ("users", String(describing: users))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func joinChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(615851205) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.joinChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func leaveChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-130635115) + channel.serialize(buffer, true) + return (FunctionDescription(name: "channels.leaveChannel", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-871347913) + channel.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.readHistory", parameters: [("channel", String(describing: channel)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func readMessageContents(channel: Api.InputChannel, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-357180360) + channel.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "channels.readMessageContents", parameters: [("channel", String(describing: channel)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func reportSpam(channel: Api.InputChannel, participant: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-196443371) + channel.serialize(buffer, true) + participant.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "channels.reportSpam", parameters: [("channel", String(describing: channel)), ("participant", String(describing: participant)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func setDiscussionGroup(broadcast: Api.InputChannel, group: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1079520178) + broadcast.serialize(buffer, true) + group.serialize(buffer, true) + return (FunctionDescription(name: "channels.setDiscussionGroup", parameters: [("broadcast", String(describing: broadcast)), ("group", String(describing: group))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func setStickers(channel: Api.InputChannel, stickerset: Api.InputStickerSet) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-359881479) + channel.serialize(buffer, true) + stickerset.serialize(buffer, true) + return (FunctionDescription(name: "channels.setStickers", parameters: [("channel", String(describing: channel)), ("stickerset", String(describing: stickerset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func toggleJoinRequest(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1277789622) + channel.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "channels.toggleJoinRequest", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func toggleJoinToSend(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-456419968) + channel.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "channels.toggleJoinToSend", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func togglePreHistoryHidden(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-356796084) + channel.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "channels.togglePreHistoryHidden", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func toggleSignatures(channel: Api.InputChannel, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(527021574) + channel.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "channels.toggleSignatures", parameters: [("channel", String(describing: channel)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func toggleSlowMode(channel: Api.InputChannel, seconds: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-304832784) + channel.serialize(buffer, true) + serializeInt32(seconds, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.toggleSlowMode", parameters: [("channel", String(describing: channel)), ("seconds", String(describing: seconds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.channels { + static func updateUsername(channel: Api.InputChannel, username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(890549214) + channel.serialize(buffer, true) + serializeString(username, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.updateUsername", parameters: [("channel", String(describing: channel)), ("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.channels { + static func viewSponsoredMessage(channel: Api.InputChannel, randomId: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1095836780) + channel.serialize(buffer, true) + serializeBytes(randomId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.viewSponsoredMessage", parameters: [("channel", String(describing: channel)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func acceptContact(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-130964977) + id.serialize(buffer, true) + return (FunctionDescription(name: "contacts.acceptContact", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.contacts { + static func addContact(flags: Int32, id: Api.InputUser, firstName: String, lastName: String, phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-386636848) + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + serializeString(firstName, buffer: buffer, boxed: false) + serializeString(lastName, buffer: buffer, boxed: false) + serializeString(phone, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.addContact", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName)), ("phone", String(describing: phone))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.contacts { + static func block(id: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1758204945) + id.serialize(buffer, true) + return (FunctionDescription(name: "contacts.block", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func blockFromReplies(flags: Int32, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(698914348) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.blockFromReplies", parameters: [("flags", String(describing: flags)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.contacts { + static func deleteByPhones(phones: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(269745566) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(phones.count)) + for item in phones { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "contacts.deleteByPhones", parameters: [("phones", String(describing: phones))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func deleteContacts(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(157945344) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "contacts.deleteContacts", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getBlocked(offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-176409329) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.getBlocked", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Blocked? in + let reader = BufferReader(buffer) + var result: Api.contacts.Blocked? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.Blocked + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getContactIDs(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) { + let buffer = Buffer() + buffer.appendInt32(2061264541) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.getContactIDs", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in + let reader = BufferReader(buffer) + var result: [Int32]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getContacts(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1574346258) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.getContacts", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Contacts? in + let reader = BufferReader(buffer) + var result: Api.contacts.Contacts? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.Contacts + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getLocated(flags: Int32, geoPoint: Api.InputGeoPoint, selfExpires: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-750207932) + serializeInt32(flags, buffer: buffer, boxed: false) + geoPoint.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(selfExpires!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "contacts.getLocated", parameters: [("flags", String(describing: flags)), ("geoPoint", String(describing: geoPoint)), ("selfExpires", String(describing: selfExpires))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getSaved() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.SavedContact]>) { + let buffer = Buffer() + buffer.appendInt32(-2098076769) + + return (FunctionDescription(name: "contacts.getSaved", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.SavedContact]? in + let reader = BufferReader(buffer) + var result: [Api.SavedContact]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.SavedContact.self) + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getStatuses() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ContactStatus]>) { + let buffer = Buffer() + buffer.appendInt32(-995929106) + + return (FunctionDescription(name: "contacts.getStatuses", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.ContactStatus]? in + let reader = BufferReader(buffer) + var result: [Api.ContactStatus]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.ContactStatus.self) + } + return result + }) + } +} +public extension Api.functions.contacts { + static func getTopPeers(flags: Int32, offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1758168906) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.getTopPeers", parameters: [("flags", String(describing: flags)), ("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.TopPeers? in + let reader = BufferReader(buffer) + var result: Api.contacts.TopPeers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.TopPeers + } + return result + }) + } +} +public extension Api.functions.contacts { + static func importContacts(contacts: [Api.InputContact]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(746589157) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(contacts.count)) + for item in contacts { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "contacts.importContacts", parameters: [("contacts", String(describing: contacts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ImportedContacts? in + let reader = BufferReader(buffer) + var result: Api.contacts.ImportedContacts? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.ImportedContacts + } + return result + }) + } +} +public extension Api.functions.contacts { + static func resetSaved() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2020263951) + + return (FunctionDescription(name: "contacts.resetSaved", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func resetTopPeerRating(category: Api.TopPeerCategory, peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(451113900) + category.serialize(buffer, true) + peer.serialize(buffer, true) + return (FunctionDescription(name: "contacts.resetTopPeerRating", parameters: [("category", String(describing: category)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func resolvePhone(phone: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1963375804) + serializeString(phone, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.resolvePhone", parameters: [("phone", String(describing: phone))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ResolvedPeer? in + let reader = BufferReader(buffer) + var result: Api.contacts.ResolvedPeer? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.ResolvedPeer + } + return result + }) + } +} +public extension Api.functions.contacts { + static func resolveUsername(username: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-113456221) + serializeString(username, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.resolveUsername", parameters: [("username", String(describing: username))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.ResolvedPeer? in + let reader = BufferReader(buffer) + var result: Api.contacts.ResolvedPeer? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.ResolvedPeer + } + return result + }) + } +} +public extension Api.functions.contacts { + static func search(q: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(301470424) + serializeString(q, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "contacts.search", parameters: [("q", String(describing: q)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.contacts.Found? in + let reader = BufferReader(buffer) + var result: Api.contacts.Found? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.contacts.Found + } + return result + }) + } +} +public extension Api.functions.contacts { + static func toggleTopPeers(enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2062238246) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "contacts.toggleTopPeers", parameters: [("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.contacts { + static func unblock(id: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1096393392) + id.serialize(buffer, true) + return (FunctionDescription(name: "contacts.unblock", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.folders { + static func deleteFolder(folderId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(472471681) + serializeInt32(folderId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "folders.deleteFolder", parameters: [("folderId", String(describing: folderId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.folders { + static func editPeerFolders(folderPeers: [Api.InputFolderPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1749536939) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(folderPeers.count)) + for item in folderPeers { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "folders.editPeerFolders", parameters: [("folderPeers", String(describing: folderPeers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.help { + static func acceptTermsOfService(id: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-294455398) + id.serialize(buffer, true) + return (FunctionDescription(name: "help.acceptTermsOfService", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.help { + static func dismissSuggestion(peer: Api.InputPeer, suggestion: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-183649631) + peer.serialize(buffer, true) + serializeString(suggestion, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.dismissSuggestion", parameters: [("peer", String(describing: peer)), ("suggestion", String(describing: suggestion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.help { + static func editUserInfo(userId: Api.InputUser, message: String, entities: [Api.MessageEntity]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1723407216) + userId.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities.count)) + for item in entities { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "help.editUserInfo", parameters: [("userId", String(describing: userId)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.UserInfo? in + let reader = BufferReader(buffer) + var result: Api.help.UserInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.UserInfo + } + return result + }) + } +} +public extension Api.functions.help { + static func getAppChangelog(prevAppVersion: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1877938321) + serializeString(prevAppVersion, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getAppChangelog", parameters: [("prevAppVersion", String(describing: prevAppVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.help { + static func getAppConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1735311088) + + return (FunctionDescription(name: "help.getAppConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.JSONValue? in + let reader = BufferReader(buffer) + var result: Api.JSONValue? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.JSONValue + } + return result + }) + } +} +public extension Api.functions.help { + static func getAppUpdate(source: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1378703997) + serializeString(source, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getAppUpdate", parameters: [("source", String(describing: source))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.AppUpdate? in + let reader = BufferReader(buffer) + var result: Api.help.AppUpdate? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.AppUpdate + } + return result + }) + } +} +public extension Api.functions.help { + static func getCdnConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1375900482) + + return (FunctionDescription(name: "help.getCdnConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.CdnConfig? in + let reader = BufferReader(buffer) + var result: Api.CdnConfig? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.CdnConfig + } + return result + }) + } +} +public extension Api.functions.help { + static func getConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-990308245) + + return (FunctionDescription(name: "help.getConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Config? in + let reader = BufferReader(buffer) + var result: Api.Config? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Config + } + return result + }) + } +} +public extension Api.functions.help { + static func getCountriesList(langCode: String, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1935116200) + serializeString(langCode, buffer: buffer, boxed: false) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getCountriesList", parameters: [("langCode", String(describing: langCode)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.CountriesList? in + let reader = BufferReader(buffer) + var result: Api.help.CountriesList? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.CountriesList + } + return result + }) + } +} +public extension Api.functions.help { + static func getDeepLinkInfo(path: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1072547679) + serializeString(path, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getDeepLinkInfo", parameters: [("path", String(describing: path))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.DeepLinkInfo? in + let reader = BufferReader(buffer) + var result: Api.help.DeepLinkInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.DeepLinkInfo + } + return result + }) + } +} +public extension Api.functions.help { + static func getInviteText() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1295590211) + + return (FunctionDescription(name: "help.getInviteText", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.InviteText? in + let reader = BufferReader(buffer) + var result: Api.help.InviteText? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.InviteText + } + return result + }) + } +} +public extension Api.functions.help { + static func getNearestDc() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(531836966) + + return (FunctionDescription(name: "help.getNearestDc", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.NearestDc? in + let reader = BufferReader(buffer) + var result: Api.NearestDc? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.NearestDc + } + return result + }) + } +} +public extension Api.functions.help { + static func getPassportConfig(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-966677240) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getPassportConfig", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PassportConfig? in + let reader = BufferReader(buffer) + var result: Api.help.PassportConfig? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.PassportConfig + } + return result + }) + } +} +public extension Api.functions.help { + static func getPremiumPromo() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1206152236) + + return (FunctionDescription(name: "help.getPremiumPromo", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PremiumPromo? in + let reader = BufferReader(buffer) + var result: Api.help.PremiumPromo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.PremiumPromo + } + return result + }) + } +} +public extension Api.functions.help { + static func getPromoData() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1063816159) + + return (FunctionDescription(name: "help.getPromoData", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.PromoData? in + let reader = BufferReader(buffer) + var result: Api.help.PromoData? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.PromoData + } + return result + }) + } +} +public extension Api.functions.help { + static func getRecentMeUrls(referer: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1036054804) + serializeString(referer, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.getRecentMeUrls", parameters: [("referer", String(describing: referer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.RecentMeUrls? in + let reader = BufferReader(buffer) + var result: Api.help.RecentMeUrls? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.RecentMeUrls + } + return result + }) + } +} +public extension Api.functions.help { + static func getSupport() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1663104819) + + return (FunctionDescription(name: "help.getSupport", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.Support? in + let reader = BufferReader(buffer) + var result: Api.help.Support? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.Support + } + return result + }) + } +} +public extension Api.functions.help { + static func getSupportName() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-748624084) + + return (FunctionDescription(name: "help.getSupportName", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.SupportName? in + let reader = BufferReader(buffer) + var result: Api.help.SupportName? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.SupportName + } + return result + }) + } +} +public extension Api.functions.help { + static func getTermsOfServiceUpdate() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(749019089) + + return (FunctionDescription(name: "help.getTermsOfServiceUpdate", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.TermsOfServiceUpdate? in + let reader = BufferReader(buffer) + var result: Api.help.TermsOfServiceUpdate? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.TermsOfServiceUpdate + } + return result + }) + } +} +public extension Api.functions.help { + static func getUserInfo(userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(59377875) + userId.serialize(buffer, true) + return (FunctionDescription(name: "help.getUserInfo", parameters: [("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.help.UserInfo? in + let reader = BufferReader(buffer) + var result: Api.help.UserInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.UserInfo + } + return result + }) + } +} +public extension Api.functions.help { + static func hidePromoData(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(505748629) + peer.serialize(buffer, true) + return (FunctionDescription(name: "help.hidePromoData", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.help { + static func saveAppLog(events: [Api.InputAppEvent]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1862465352) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(events.count)) + for item in events { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "help.saveAppLog", parameters: [("events", String(describing: events))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.help { + static func setBotUpdatesStatus(pendingUpdatesCount: Int32, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-333262899) + serializeInt32(pendingUpdatesCount, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + return (FunctionDescription(name: "help.setBotUpdatesStatus", parameters: [("pendingUpdatesCount", String(describing: pendingUpdatesCount)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.help { + static func test() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1058929929) + + return (FunctionDescription(name: "help.test", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.langpack { + static func getDifference(langPack: String, langCode: String, fromVersion: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-845657435) + serializeString(langPack, buffer: buffer, boxed: false) + serializeString(langCode, buffer: buffer, boxed: false) + serializeInt32(fromVersion, buffer: buffer, boxed: false) + return (FunctionDescription(name: "langpack.getDifference", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode)), ("fromVersion", String(describing: fromVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackDifference? in + let reader = BufferReader(buffer) + var result: Api.LangPackDifference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.LangPackDifference + } + return result + }) + } +} +public extension Api.functions.langpack { + static func getLangPack(langPack: String, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-219008246) + serializeString(langPack, buffer: buffer, boxed: false) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "langpack.getLangPack", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackDifference? in + let reader = BufferReader(buffer) + var result: Api.LangPackDifference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.LangPackDifference + } + return result + }) + } +} +public extension Api.functions.langpack { + static func getLanguage(langPack: String, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1784243458) + serializeString(langPack, buffer: buffer, boxed: false) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "langpack.getLanguage", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.LangPackLanguage? in + let reader = BufferReader(buffer) + var result: Api.LangPackLanguage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.LangPackLanguage + } + return result + }) + } +} +public extension Api.functions.langpack { + static func getLanguages(langPack: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.LangPackLanguage]>) { + let buffer = Buffer() + buffer.appendInt32(1120311183) + serializeString(langPack, buffer: buffer, boxed: false) + return (FunctionDescription(name: "langpack.getLanguages", parameters: [("langPack", String(describing: langPack))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.LangPackLanguage]? in + let reader = BufferReader(buffer) + var result: [Api.LangPackLanguage]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackLanguage.self) + } + return result + }) + } +} +public extension Api.functions.langpack { + static func getStrings(langPack: String, langCode: String, keys: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.LangPackString]>) { + let buffer = Buffer() + buffer.appendInt32(-269862909) + serializeString(langPack, buffer: buffer, boxed: false) + serializeString(langCode, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(keys.count)) + for item in keys { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "langpack.getStrings", parameters: [("langPack", String(describing: langPack)), ("langCode", String(describing: langCode)), ("keys", String(describing: keys))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.LangPackString]? in + let reader = BufferReader(buffer) + var result: [Api.LangPackString]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.LangPackString.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func acceptEncryption(peer: Api.InputEncryptedChat, gB: Buffer, keyFingerprint: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1035731989) + peer.serialize(buffer, true) + serializeBytes(gB, buffer: buffer, boxed: false) + serializeInt64(keyFingerprint, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.acceptEncryption", parameters: [("peer", String(describing: peer)), ("gB", String(describing: gB)), ("keyFingerprint", String(describing: keyFingerprint))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedChat? in + let reader = BufferReader(buffer) + var result: Api.EncryptedChat? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EncryptedChat + } + return result + }) + } +} +public extension Api.functions.messages { + static func acceptUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1322487515) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.acceptUrlAuth", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("buttonId", String(describing: buttonId)), ("url", String(describing: url))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in + let reader = BufferReader(buffer) + var result: Api.UrlAuthResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.UrlAuthResult + } + return result + }) + } +} +public extension Api.functions.messages { + static func addChatUser(chatId: Int64, userId: Api.InputUser, fwdLimit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-230206493) + serializeInt64(chatId, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + serializeInt32(fwdLimit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.addChatUser", parameters: [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("fwdLimit", String(describing: fwdLimit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func checkChatInvite(hash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1051570619) + serializeString(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.checkChatInvite", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ChatInvite? in + let reader = BufferReader(buffer) + var result: Api.ChatInvite? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.ChatInvite + } + return result + }) + } +} +public extension Api.functions.messages { + static func checkHistoryImport(importHead: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1140726259) + serializeString(importHead, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.checkHistoryImport", parameters: [("importHead", String(describing: importHead))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImportParsed? in + let reader = BufferReader(buffer) + var result: Api.messages.HistoryImportParsed? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImportParsed + } + return result + }) + } +} +public extension Api.functions.messages { + static func checkHistoryImportPeer(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1573261059) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.checkHistoryImportPeer", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.CheckedHistoryImportPeer? in + let reader = BufferReader(buffer) + var result: Api.messages.CheckedHistoryImportPeer? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.CheckedHistoryImportPeer + } + return result + }) + } +} +public extension Api.functions.messages { + static func clearAllDrafts() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2119757468) + + return (FunctionDescription(name: "messages.clearAllDrafts", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func clearRecentStickers(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1986437075) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.clearRecentStickers", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func createChat(users: [Api.InputUser], title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(164303470) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + serializeString(title, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.createChat", parameters: [("users", String(describing: users)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1540419152) + serializeInt64(chatId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.deleteChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteChatUser(flags: Int32, chatId: Int64, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1575461717) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(chatId, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + return (FunctionDescription(name: "messages.deleteChatUser", parameters: [("flags", String(describing: flags)), ("chatId", String(describing: chatId)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-731601877) + peer.serialize(buffer, true) + serializeString(link, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.deleteExportedChatInvite", parameters: [("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteHistory(flags: Int32, peer: Api.InputPeer, maxId: Int32, minDate: Int32?, maxDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1332768214) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(minDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(maxDate!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.deleteHistory", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("maxId", String(describing: maxId)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteMessages(flags: Int32, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-443640366) + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.deleteMessages", parameters: [("flags", String(describing: flags)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages + } + return result + }) + } +} +public extension Api.functions.messages { + static func deletePhoneCallHistory(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-104078327) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.deletePhoneCallHistory", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedFoundMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedFoundMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedFoundMessages + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteRevokedExportedChatInvites(peer: Api.InputPeer, adminId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1452833749) + peer.serialize(buffer, true) + adminId.serialize(buffer, true) + return (FunctionDescription(name: "messages.deleteRevokedExportedChatInvites", parameters: [("peer", String(describing: peer)), ("adminId", String(describing: adminId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func deleteScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1504586518) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.deleteScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func discardEncryption(flags: Int32, chatId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-208425312) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(chatId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.discardEncryption", parameters: [("flags", String(describing: flags)), ("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func editChatAbout(peer: Api.InputPeer, about: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-554301545) + peer.serialize(buffer, true) + serializeString(about, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.editChatAbout", parameters: [("peer", String(describing: peer)), ("about", String(describing: about))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func editChatAdmin(chatId: Int64, userId: Api.InputUser, isAdmin: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1470377534) + serializeInt64(chatId, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + isAdmin.serialize(buffer, true) + return (FunctionDescription(name: "messages.editChatAdmin", parameters: [("chatId", String(describing: chatId)), ("userId", String(describing: userId)), ("isAdmin", String(describing: isAdmin))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func editChatDefaultBannedRights(peer: Api.InputPeer, bannedRights: Api.ChatBannedRights) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1517917375) + peer.serialize(buffer, true) + bannedRights.serialize(buffer, true) + return (FunctionDescription(name: "messages.editChatDefaultBannedRights", parameters: [("peer", String(describing: peer)), ("bannedRights", String(describing: bannedRights))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func editChatPhoto(chatId: Int64, photo: Api.InputChatPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(903730804) + serializeInt64(chatId, buffer: buffer, boxed: false) + photo.serialize(buffer, true) + return (FunctionDescription(name: "messages.editChatPhoto", parameters: [("chatId", String(describing: chatId)), ("photo", String(describing: photo))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func editChatTitle(chatId: Int64, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1937260541) + serializeInt64(chatId, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.editChatTitle", parameters: [("chatId", String(describing: chatId)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func editExportedChatInvite(flags: Int32, peer: Api.InputPeer, link: String, expireDate: Int32?, usageLimit: Int32?, requestNeeded: Api.Bool?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1110823051) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeString(link, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {requestNeeded!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.editExportedChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("requestNeeded", String(describing: requestNeeded)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in + let reader = BufferReader(buffer) + var result: Api.messages.ExportedChatInvite? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite + } + return result + }) + } +} +public extension Api.functions.messages { + static func editInlineBotMessage(flags: Int32, id: Api.InputBotInlineMessageID, message: String?, media: Api.InputMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2091549254) + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "messages.editInlineBotMessage", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func editMessage(flags: Int32, peer: Api.InputPeer, id: Int32, message: String?, media: Api.InputMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1224152952) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 11) != 0 {serializeString(message!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 15) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.editMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("message", String(describing: message)), ("media", String(describing: media)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1607670315) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in + let reader = BufferReader(buffer) + var result: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } + return result + }) + } +} +public extension Api.functions.messages { + static func faveSticker(id: Api.InputDocument, unfave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1174420133) + id.serialize(buffer, true) + unfave.serialize(buffer, true) + return (FunctionDescription(name: "messages.faveSticker", parameters: [("id", String(describing: id)), ("unfave", String(describing: unfave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-869258997) + serializeInt32(flags, buffer: buffer, boxed: false) + fromPeer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(randomId.count)) + for item in randomId { + serializeInt64(item, buffer: buffer, boxed: false) + } + toPeer.serialize(buffer, true) + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAdminsWithInvites(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(958457583) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.getAdminsWithInvites", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatAdminsWithInvites? in + let reader = BufferReader(buffer) + var result: Api.messages.ChatAdminsWithInvites? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ChatAdminsWithInvites + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAllChats(exceptIds: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2023787330) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(exceptIds.count)) + for item in exceptIds { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getAllChats", parameters: [("exceptIds", String(describing: exceptIds))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAllDrafts() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1782549861) + + return (FunctionDescription(name: "messages.getAllDrafts", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAllStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1197432408) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getAllStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AllStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.AllStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AllStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getArchivedStickers(flags: Int32, offsetId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1475442322) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getArchivedStickers", parameters: [("flags", String(describing: flags)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ArchivedStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.ArchivedStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ArchivedStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAttachMenuBot(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1998676370) + bot.serialize(buffer, true) + return (FunctionDescription(name: "messages.getAttachMenuBot", parameters: [("bot", String(describing: bot))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AttachMenuBotsBot? in + let reader = BufferReader(buffer) + var result: Api.AttachMenuBotsBot? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.AttachMenuBotsBot + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAttachMenuBots(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(385663691) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getAttachMenuBots", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.AttachMenuBots? in + let reader = BufferReader(buffer) + var result: Api.AttachMenuBots? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.AttachMenuBots + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAttachedStickers(media: Api.InputStickeredMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StickerSetCovered]>) { + let buffer = Buffer() + buffer.appendInt32(-866424884) + media.serialize(buffer, true) + return (FunctionDescription(name: "messages.getAttachedStickers", parameters: [("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.StickerSetCovered]? in + let reader = BufferReader(buffer) + var result: [Api.StickerSetCovered]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerSetCovered.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getAvailableReactions(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(417243308) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getAvailableReactions", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AvailableReactions? in + let reader = BufferReader(buffer) + var result: Api.messages.AvailableReactions? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AvailableReactions + } + return result + }) + } +} +public extension Api.functions.messages { + static func getBotCallbackAnswer(flags: Int32, peer: Api.InputPeer, msgId: Int32, data: Buffer?, password: Api.InputCheckPasswordSRP?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1824339449) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(data!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {password!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.getBotCallbackAnswer", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("data", String(describing: data)), ("password", String(describing: password))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.BotCallbackAnswer? in + let reader = BufferReader(buffer) + var result: Api.messages.BotCallbackAnswer? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.BotCallbackAnswer + } + return result + }) + } +} +public extension Api.functions.messages { + static func getChatInviteImporters(flags: Int32, peer: Api.InputPeer, link: String?, q: String?, offsetDate: Int32, offsetUser: Api.InputUser, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-553329330) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(q!, buffer: buffer, boxed: false)} + serializeInt32(offsetDate, buffer: buffer, boxed: false) + offsetUser.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getChatInviteImporters", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link)), ("q", String(describing: q)), ("offsetDate", String(describing: offsetDate)), ("offsetUser", String(describing: offsetUser)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatInviteImporters? in + let reader = BufferReader(buffer) + var result: Api.messages.ChatInviteImporters? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ChatInviteImporters + } + return result + }) + } +} +public extension Api.functions.messages { + static func getChats(id: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1240027791) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getChats", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.messages { + static func getCommonChats(userId: Api.InputUser, maxId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-468934396) + userId.serialize(buffer, true) + serializeInt64(maxId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getCommonChats", parameters: [("userId", String(describing: userId)), ("maxId", String(describing: maxId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + let reader = BufferReader(buffer) + var result: Api.messages.Chats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Chats + } + return result + }) + } +} +public extension Api.functions.messages { + static func getCustomEmojiDocuments(documentId: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.Document]>) { + let buffer = Buffer() + buffer.appendInt32(-643100844) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documentId.count)) + for item in documentId { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getCustomEmojiDocuments", parameters: [("documentId", String(describing: documentId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.Document]? in + let reader = BufferReader(buffer) + var result: [Api.Document]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDhConfig(version: Int32, randomLength: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(651135312) + serializeInt32(version, buffer: buffer, boxed: false) + serializeInt32(randomLength, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getDhConfig", parameters: [("version", String(describing: version)), ("randomLength", String(describing: randomLength))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.DhConfig? in + let reader = BufferReader(buffer) + var result: Api.messages.DhConfig? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.DhConfig + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDialogFilters() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogFilter]>) { + let buffer = Buffer() + buffer.appendInt32(-241247891) + + return (FunctionDescription(name: "messages.getDialogFilters", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogFilter]? in + let reader = BufferReader(buffer) + var result: [Api.DialogFilter]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilter.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDialogUnreadMarks() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogPeer]>) { + let buffer = Buffer() + buffer.appendInt32(585256482) + + return (FunctionDescription(name: "messages.getDialogUnreadMarks", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogPeer]? in + let reader = BufferReader(buffer) + var result: [Api.DialogPeer]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogPeer.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDialogs(flags: Int32, folderId: Int32?, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1594569905) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeInt32(offsetDate, buffer: buffer, boxed: false) + serializeInt32(offsetId, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getDialogs", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("offsetDate", String(describing: offsetDate)), ("offsetId", String(describing: offsetId)), ("offsetPeer", String(describing: offsetPeer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Dialogs? in + let reader = BufferReader(buffer) + var result: Api.messages.Dialogs? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Dialogs + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDiscussionMessage(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1147761405) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getDiscussionMessage", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.DiscussionMessage? in + let reader = BufferReader(buffer) + var result: Api.messages.DiscussionMessage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.DiscussionMessage + } + return result + }) + } +} +public extension Api.functions.messages { + static func getDocumentByHash(sha256: Buffer, size: Int64, mimeType: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1309538785) + serializeBytes(sha256, buffer: buffer, boxed: false) + serializeInt64(size, buffer: buffer, boxed: false) + serializeString(mimeType, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getDocumentByHash", parameters: [("sha256", String(describing: sha256)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Document? in + let reader = BufferReader(buffer) + var result: Api.Document? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Document + } + return result + }) + } +} +public extension Api.functions.messages { + static func getEmojiKeywords(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(899735650) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiKeywords", parameters: [("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiKeywordsDifference? in + let reader = BufferReader(buffer) + var result: Api.EmojiKeywordsDifference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EmojiKeywordsDifference + } + return result + }) + } +} +public extension Api.functions.messages { + static func getEmojiKeywordsDifference(langCode: String, fromVersion: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(352892591) + serializeString(langCode, buffer: buffer, boxed: false) + serializeInt32(fromVersion, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiKeywordsDifference", parameters: [("langCode", String(describing: langCode)), ("fromVersion", String(describing: fromVersion))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiKeywordsDifference? in + let reader = BufferReader(buffer) + var result: Api.EmojiKeywordsDifference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EmojiKeywordsDifference + } + return result + }) + } +} +public extension Api.functions.messages { + static func getEmojiKeywordsLanguages(langCodes: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.EmojiLanguage]>) { + let buffer = Buffer() + buffer.appendInt32(1318675378) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(langCodes.count)) + for item in langCodes { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getEmojiKeywordsLanguages", parameters: [("langCodes", String(describing: langCodes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.EmojiLanguage]? in + let reader = BufferReader(buffer) + var result: [Api.EmojiLanguage]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.EmojiLanguage.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getEmojiStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-67329649) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AllStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.AllStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AllStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getEmojiURL(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-709817306) + serializeString(langCode, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getEmojiURL", parameters: [("langCode", String(describing: langCode))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EmojiURL? in + let reader = BufferReader(buffer) + var result: Api.EmojiURL? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EmojiURL + } + return result + }) + } +} +public extension Api.functions.messages { + static func getExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1937010524) + peer.serialize(buffer, true) + serializeString(link, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getExportedChatInvite", parameters: [("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in + let reader = BufferReader(buffer) + var result: Api.messages.ExportedChatInvite? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite + } + return result + }) + } +} +public extension Api.functions.messages { + static func getExportedChatInvites(flags: Int32, peer: Api.InputPeer, adminId: Api.InputUser, offsetDate: Int32?, offsetLink: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1565154314) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + adminId.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(offsetLink!, buffer: buffer, boxed: false)} + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getExportedChatInvites", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("adminId", String(describing: adminId)), ("offsetDate", String(describing: offsetDate)), ("offsetLink", String(describing: offsetLink)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvites? in + let reader = BufferReader(buffer) + var result: Api.messages.ExportedChatInvites? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvites + } + return result + }) + } +} +public extension Api.functions.messages { + static func getFavedStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(82946729) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getFavedStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FavedStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.FavedStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.FavedStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getFeaturedEmojiStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(248473398) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getFeaturedEmojiStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.FeaturedStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getFeaturedStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1685588756) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getFeaturedStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.FeaturedStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getFullChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1364194508) + serializeInt64(chatId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getFullChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatFull? in + let reader = BufferReader(buffer) + var result: Api.messages.ChatFull? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.ChatFull + } + return result + }) + } +} +public extension Api.functions.messages { + static func getGameHighScores(peer: Api.InputPeer, id: Int32, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-400399203) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + return (FunctionDescription(name: "messages.getGameHighScores", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HighScores? in + let reader = BufferReader(buffer) + var result: Api.messages.HighScores? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.HighScores + } + return result + }) + } +} +public extension Api.functions.messages { + static func getHistory(peer: Api.InputPeer, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1143203525) + peer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(offsetDate, buffer: buffer, boxed: false) + serializeInt32(addOffset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(minId, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getHistory", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getInlineBotResults(flags: Int32, bot: Api.InputUser, peer: Api.InputPeer, geoPoint: Api.InputGeoPoint?, query: String, offset: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1364105629) + serializeInt32(flags, buffer: buffer, boxed: false) + bot.serialize(buffer, true) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {geoPoint!.serialize(buffer, true)} + serializeString(query, buffer: buffer, boxed: false) + serializeString(offset, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getInlineBotResults", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("peer", String(describing: peer)), ("geoPoint", String(describing: geoPoint)), ("query", String(describing: query)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.BotResults? in + let reader = BufferReader(buffer) + var result: Api.messages.BotResults? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.BotResults + } + return result + }) + } +} +public extension Api.functions.messages { + static func getInlineGameHighScores(id: Api.InputBotInlineMessageID, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(258170395) + id.serialize(buffer, true) + userId.serialize(buffer, true) + return (FunctionDescription(name: "messages.getInlineGameHighScores", parameters: [("id", String(describing: id)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HighScores? in + let reader = BufferReader(buffer) + var result: Api.messages.HighScores? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.HighScores + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMaskStickers(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1678738104) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getMaskStickers", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AllStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.AllStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AllStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessageEditData(peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-39416522) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getMessageEditData", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageEditData? in + let reader = BufferReader(buffer) + var result: Api.messages.MessageEditData? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.MessageEditData + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessageReactionsList(flags: Int32, peer: Api.InputPeer, id: Int32, reaction: String?, offset: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-521245833) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(offset!, buffer: buffer, boxed: false)} + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getMessageReactionsList", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("reaction", String(describing: reaction)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageReactionsList? in + let reader = BufferReader(buffer) + var result: Api.messages.MessageReactionsList? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.MessageReactionsList + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessageReadParticipants(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { + let buffer = Buffer() + buffer.appendInt32(745510839) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getMessageReadParticipants", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in + let reader = BufferReader(buffer) + var result: [Int64]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessages(id: [Api.InputMessage]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1673946374) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "messages.getMessages", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessagesReactions(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1950707482) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getMessagesReactions", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func getMessagesViews(peer: Api.InputPeer, id: [Int32], increment: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1468322785) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + increment.serialize(buffer, true) + return (FunctionDescription(name: "messages.getMessagesViews", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("increment", String(describing: increment))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MessageViews? in + let reader = BufferReader(buffer) + var result: Api.messages.MessageViews? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.MessageViews + } + return result + }) + } +} +public extension Api.functions.messages { + static func getOldFeaturedStickers(offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2127598753) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getOldFeaturedStickers", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FeaturedStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.FeaturedStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.FeaturedStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getOnlines(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1848369232) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.getOnlines", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ChatOnlines? in + let reader = BufferReader(buffer) + var result: Api.ChatOnlines? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.ChatOnlines + } + return result + }) + } +} +public extension Api.functions.messages { + static func getPeerDialogs(peers: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-462373635) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "messages.getPeerDialogs", parameters: [("peers", String(describing: peers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerDialogs? in + let reader = BufferReader(buffer) + var result: Api.messages.PeerDialogs? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.PeerDialogs + } + return result + }) + } +} +public extension Api.functions.messages { + static func getPeerSettings(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-270948702) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.getPeerSettings", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerSettings? in + let reader = BufferReader(buffer) + var result: Api.messages.PeerSettings? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.PeerSettings + } + return result + }) + } +} +public extension Api.functions.messages { + static func getPinnedDialogs(folderId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-692498958) + serializeInt32(folderId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getPinnedDialogs", parameters: [("folderId", String(describing: folderId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.PeerDialogs? in + let reader = BufferReader(buffer) + var result: Api.messages.PeerDialogs? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.PeerDialogs + } + return result + }) + } +} +public extension Api.functions.messages { + static func getPollResults(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1941660731) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getPollResults", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func getPollVotes(flags: Int32, peer: Api.InputPeer, id: Int32, option: Buffer?, offset: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1200736242) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeBytes(option!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(offset!, buffer: buffer, boxed: false)} + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getPollVotes", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("option", String(describing: option)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.VotesList? in + let reader = BufferReader(buffer) + var result: Api.messages.VotesList? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.VotesList + } + return result + }) + } +} +public extension Api.functions.messages { + static func getRecentLocations(peer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1881817312) + peer.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getRecentLocations", parameters: [("peer", String(describing: peer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getRecentStickers(flags: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1649852357) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getRecentStickers", parameters: [("flags", String(describing: flags)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.RecentStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.RecentStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.RecentStickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getReplies(peer: Api.InputPeer, msgId: Int32, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(584962828) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(offsetDate, buffer: buffer, boxed: false) + serializeInt32(addOffset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(minId, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getReplies", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSavedGifs(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1559270965) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getSavedGifs", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedGifs? in + let reader = BufferReader(buffer) + var result: Api.messages.SavedGifs? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SavedGifs + } + return result + }) + } +} +public extension Api.functions.messages { + static func getScheduledHistory(peer: Api.InputPeer, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-183077365) + peer.serialize(buffer, true) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getScheduledHistory", parameters: [("peer", String(describing: peer)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1111817116) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.getScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSearchCounters(peer: Api.InputPeer, filters: [Api.MessagesFilter]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.messages.SearchCounter]>) { + let buffer = Buffer() + buffer.appendInt32(1932455680) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(filters.count)) + for item in filters { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "messages.getSearchCounters", parameters: [("peer", String(describing: peer)), ("filters", String(describing: filters))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.messages.SearchCounter]? in + let reader = BufferReader(buffer) + var result: [Api.messages.SearchCounter]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.messages.SearchCounter.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSearchResultsCalendar(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, offsetDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1240514025) + peer.serialize(buffer, true) + filter.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(offsetDate, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getSearchResultsCalendar", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsCalendar? in + let reader = BufferReader(buffer) + var result: Api.messages.SearchResultsCalendar? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SearchResultsCalendar + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSearchResultsPositions(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1855292323) + peer.serialize(buffer, true) + filter.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getSearchResultsPositions", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsPositions? in + let reader = BufferReader(buffer) + var result: Api.messages.SearchResultsPositions? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SearchResultsPositions + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSplitRanges() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.MessageRange]>) { + let buffer = Buffer() + buffer.appendInt32(486505992) + + return (FunctionDescription(name: "messages.getSplitRanges", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.MessageRange]? in + let reader = BufferReader(buffer) + var result: [Api.MessageRange]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageRange.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getStickerSet(stickerset: Api.InputStickerSet, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-928977804) + stickerset.serialize(buffer, true) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getStickerSet", parameters: [("stickerset", String(describing: stickerset)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.messages { + static func getStickers(emoticon: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-710552671) + serializeString(emoticon, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getStickers", parameters: [("emoticon", String(describing: emoticon)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Stickers? in + let reader = BufferReader(buffer) + var result: Api.messages.Stickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Stickers + } + return result + }) + } +} +public extension Api.functions.messages { + static func getSuggestedDialogFilters() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.DialogFilterSuggested]>) { + let buffer = Buffer() + buffer.appendInt32(-1566780372) + + return (FunctionDescription(name: "messages.getSuggestedDialogFilters", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.DialogFilterSuggested]? in + let reader = BufferReader(buffer) + var result: [Api.DialogFilterSuggested]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilterSuggested.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func getUnreadMentions(peer: Api.InputPeer, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1180140658) + peer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(addOffset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(minId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getUnreadMentions", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getUnreadReactions(peer: Api.InputPeer, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-396644838) + peer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(addOffset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(minId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getUnreadReactions", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func getWebPage(url: String, hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(852135825) + serializeString(url, buffer: buffer, boxed: false) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getWebPage", parameters: [("url", String(describing: url)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebPage? in + let reader = BufferReader(buffer) + var result: Api.WebPage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.WebPage + } + return result + }) + } +} +public extension Api.functions.messages { + static func getWebPagePreview(flags: Int32, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1956073268) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "messages.getWebPagePreview", parameters: [("flags", String(describing: flags)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in + let reader = BufferReader(buffer) + var result: Api.MessageMedia? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + return result + }) + } +} +public extension Api.functions.messages { + static func hideAllChatJoinRequests(flags: Int32, peer: Api.InputPeer, link: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-528091926) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 1) != 0 {serializeString(link!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.hideAllChatJoinRequests", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("link", String(describing: link))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func hideChatJoinRequest(flags: Int32, peer: Api.InputPeer, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2145904661) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + userId.serialize(buffer, true) + return (FunctionDescription(name: "messages.hideChatJoinRequest", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("userId", String(describing: userId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func hidePeerSettingsBar(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1336717624) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.hidePeerSettingsBar", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func importChatInvite(hash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1817183516) + serializeString(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.importChatInvite", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func initHistoryImport(peer: Api.InputPeer, file: Api.InputFile, mediaCount: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(873008187) + peer.serialize(buffer, true) + file.serialize(buffer, true) + serializeInt32(mediaCount, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.initHistoryImport", parameters: [("peer", String(describing: peer)), ("file", String(describing: file)), ("mediaCount", String(describing: mediaCount))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImport? in + let reader = BufferReader(buffer) + var result: Api.messages.HistoryImport? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImport + } + return result + }) + } +} +public extension Api.functions.messages { + static func installStickerSet(stickerset: Api.InputStickerSet, archived: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-946871200) + stickerset.serialize(buffer, true) + archived.serialize(buffer, true) + return (FunctionDescription(name: "messages.installStickerSet", parameters: [("stickerset", String(describing: stickerset)), ("archived", String(describing: archived))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSetInstallResult? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSetInstallResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSetInstallResult + } + return result + }) + } +} +public extension Api.functions.messages { + static func markDialogUnread(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1031349873) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.markDialogUnread", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func migrateChat(chatId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1568189671) + serializeInt64(chatId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.migrateChat", parameters: [("chatId", String(describing: chatId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func prolongWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, queryId: Int64, replyToMsgId: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-362824498) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + bot.serialize(buffer, true) + serializeInt64(queryId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.prolongWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("queryId", String(describing: queryId)), ("replyToMsgId", String(describing: replyToMsgId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func rateTranscribedAudio(peer: Api.InputPeer, msgId: Int32, transcriptionId: Int64, good: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2132608815) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt64(transcriptionId, buffer: buffer, boxed: false) + good.serialize(buffer, true) + return (FunctionDescription(name: "messages.rateTranscribedAudio", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("transcriptionId", String(describing: transcriptionId)), ("good", String(describing: good))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func readDiscussion(peer: Api.InputPeer, msgId: Int32, readMaxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-147740172) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt32(readMaxId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.readDiscussion", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("readMaxId", String(describing: readMaxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func readEncryptedHistory(peer: Api.InputEncryptedChat, maxDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2135648522) + peer.serialize(buffer, true) + serializeInt32(maxDate, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.readEncryptedHistory", parameters: [("peer", String(describing: peer)), ("maxDate", String(describing: maxDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func readFeaturedStickers(id: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1527873830) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.readFeaturedStickers", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func readHistory(peer: Api.InputPeer, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(238054714) + peer.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.readHistory", parameters: [("peer", String(describing: peer)), ("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages + } + return result + }) + } +} +public extension Api.functions.messages { + static func readMentions(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(251759059) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.readMentions", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} +public extension Api.functions.messages { + static func readMessageContents(id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(916930423) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.readMessageContents", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedMessages? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedMessages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedMessages + } + return result + }) + } +} +public extension Api.functions.messages { + static func readReactions(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2099097129) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.readReactions", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} +public extension Api.functions.messages { + static func receivedMessages(maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.ReceivedNotifyMessage]>) { + let buffer = Buffer() + buffer.appendInt32(94983360) + serializeInt32(maxId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.receivedMessages", parameters: [("maxId", String(describing: maxId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.ReceivedNotifyMessage]? in + let reader = BufferReader(buffer) + var result: [Api.ReceivedNotifyMessage]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.ReceivedNotifyMessage.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func receivedQueue(maxQts: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { + let buffer = Buffer() + buffer.appendInt32(1436924774) + serializeInt32(maxQts, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.receivedQueue", parameters: [("maxQts", String(describing: maxQts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in + let reader = BufferReader(buffer) + var result: [Int64]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + return result + }) + } +} +public extension Api.functions.messages { + static func reorderPinnedDialogs(flags: Int32, folderId: Int32, order: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(991616823) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(folderId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "messages.reorderPinnedDialogs", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func reorderStickerSets(flags: Int32, order: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2016638777) + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt64(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.reorderStickerSets", parameters: [("flags", String(describing: flags)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func report(peer: Api.InputPeer, id: [Int32], reason: Api.ReportReason, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1991005362) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + reason.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.report", parameters: [("peer", String(describing: peer)), ("id", String(describing: id)), ("reason", String(describing: reason)), ("message", String(describing: message))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func reportEncryptedSpam(peer: Api.InputEncryptedChat) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1259113487) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.reportEncryptedSpam", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func reportSpam(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-820669733) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.reportSpam", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func requestEncryption(userId: Api.InputUser, randomId: Int32, gA: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-162681021) + userId.serialize(buffer, true) + serializeInt32(randomId, buffer: buffer, boxed: false) + serializeBytes(gA, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.requestEncryption", parameters: [("userId", String(describing: userId)), ("randomId", String(describing: randomId)), ("gA", String(describing: gA))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedChat? in + let reader = BufferReader(buffer) + var result: Api.EncryptedChat? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EncryptedChat + } + return result + }) + } +} +public extension Api.functions.messages { + static func requestSimpleWebView(flags: Int32, bot: Api.InputUser, url: String, themeParams: Api.DataJSON?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1790652275) + serializeInt32(flags, buffer: buffer, boxed: false) + bot.serialize(buffer, true) + serializeString(url, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.requestSimpleWebView", parameters: [("flags", String(describing: flags)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("themeParams", String(describing: themeParams))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.SimpleWebViewResult? in + let reader = BufferReader(buffer) + var result: Api.SimpleWebViewResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.SimpleWebViewResult + } + return result + }) + } +} +public extension Api.functions.messages { + static func requestUrlAuth(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, buttonId: Int32?, url: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(428848198) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {peer!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(buttonId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.requestUrlAuth", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("buttonId", String(describing: buttonId)), ("url", String(describing: url))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.UrlAuthResult? in + let reader = BufferReader(buffer) + var result: Api.UrlAuthResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.UrlAuthResult + } + return result + }) + } +} +public extension Api.functions.messages { + static func requestWebView(flags: Int32, peer: Api.InputPeer, bot: Api.InputUser, url: String?, startParam: String?, themeParams: Api.DataJSON?, replyToMsgId: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1850648527) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + bot.serialize(buffer, true) + if Int(flags) & Int(1 << 1) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {themeParams!.serialize(buffer, true)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.requestWebView", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("bot", String(describing: bot)), ("url", String(describing: url)), ("startParam", String(describing: startParam)), ("themeParams", String(describing: themeParams)), ("replyToMsgId", String(describing: replyToMsgId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewResult? in + let reader = BufferReader(buffer) + var result: Api.WebViewResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.WebViewResult + } + return result + }) + } +} +public extension Api.functions.messages { + static func saveDefaultSendAs(peer: Api.InputPeer, sendAs: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-855777386) + peer.serialize(buffer, true) + sendAs.serialize(buffer, true) + return (FunctionDescription(name: "messages.saveDefaultSendAs", parameters: [("peer", String(describing: peer)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func saveDraft(flags: Int32, replyToMsgId: Int32?, peer: Api.InputPeer, message: String, entities: [Api.MessageEntity]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1137057461) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + peer.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "messages.saveDraft", parameters: [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("peer", String(describing: peer)), ("message", String(describing: message)), ("entities", String(describing: entities))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func saveGif(id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(846868683) + id.serialize(buffer, true) + unsave.serialize(buffer, true) + return (FunctionDescription(name: "messages.saveGif", parameters: [("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func saveRecentSticker(flags: Int32, id: Api.InputDocument, unsave: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(958863608) + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + unsave.serialize(buffer, true) + return (FunctionDescription(name: "messages.saveRecentSticker", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("unsave", String(describing: unsave))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func search(flags: Int32, peer: Api.InputPeer, q: String, fromId: Api.InputPeer?, topMsgId: Int32?, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1593989278) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeString(q, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {fromId!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} + filter.serialize(buffer, true) + serializeInt32(minDate, buffer: buffer, boxed: false) + serializeInt32(maxDate, buffer: buffer, boxed: false) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(addOffset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(minId, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.search", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("q", String(describing: q)), ("fromId", String(describing: fromId)), ("topMsgId", String(describing: topMsgId)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func searchGlobal(flags: Int32, folderId: Int32?, q: String, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1271290010) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeString(q, buffer: buffer, boxed: false) + filter.serialize(buffer, true) + serializeInt32(minDate, buffer: buffer, boxed: false) + serializeInt32(maxDate, buffer: buffer, boxed: false) + serializeInt32(offsetRate, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.searchGlobal", parameters: [("flags", String(describing: flags)), ("folderId", String(describing: folderId)), ("q", String(describing: q)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetRate", String(describing: offsetRate)), ("offsetPeer", String(describing: offsetPeer)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func searchSentMedia(q: String, filter: Api.MessagesFilter, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(276705696) + serializeString(q, buffer: buffer, boxed: false) + filter.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.searchSentMedia", parameters: [("q", String(describing: q)), ("filter", String(describing: filter)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.messages { + static func searchStickerSets(flags: Int32, q: String, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(896555914) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(q, buffer: buffer, boxed: false) + serializeInt64(hash, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.searchStickerSets", parameters: [("flags", String(describing: flags)), ("q", String(describing: q)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.FoundStickerSets? in + let reader = BufferReader(buffer) + var result: Api.messages.FoundStickerSets? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.FoundStickerSets + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendEncrypted(flags: Int32, peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1157265941) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.sendEncrypted", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in + let reader = BufferReader(buffer) + var result: Api.messages.SentEncryptedMessage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendEncryptedFile(flags: Int32, peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer, file: Api.InputEncryptedFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1431914525) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + file.serialize(buffer, true) + return (FunctionDescription(name: "messages.sendEncryptedFile", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in + let reader = BufferReader(buffer) + var result: Api.messages.SentEncryptedMessage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendEncryptedService(peer: Api.InputEncryptedChat, randomId: Int64, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(852769188) + peer.serialize(buffer, true) + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeBytes(data, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.sendEncryptedService", parameters: [("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SentEncryptedMessage? in + let reader = BufferReader(buffer) + var result: Api.messages.SentEncryptedMessage? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.SentEncryptedMessage + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendInlineBotResult(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, randomId: Int64, queryId: Int64, id: String, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2057376407) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + serializeString(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.sendInlineBotResult", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("randomId", String(describing: randomId)), ("queryId", String(describing: queryId)), ("id", String(describing: id)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendMedia(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, media: Api.InputMedia, message: String, randomId: Int64, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-497026848) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + media.serialize(buffer, true) + serializeString(message, buffer: buffer, boxed: false) + serializeInt64(randomId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.sendMedia", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("media", String(describing: media)), ("message", String(describing: message)), ("randomId", String(describing: randomId)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendMessage(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, message: String, randomId: Int64, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(228423076) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + serializeString(message, buffer: buffer, boxed: false) + serializeInt64(randomId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {replyMarkup!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.sendMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("message", String(describing: message)), ("randomId", String(describing: randomId)), ("replyMarkup", String(describing: replyMarkup)), ("entities", String(describing: entities)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendMultiMedia(flags: Int32, peer: Api.InputPeer, replyToMsgId: Int32?, multiMedia: [Api.InputSingleMedia], scheduleDate: Int32?, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-134016113) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(multiMedia.count)) + for item in multiMedia { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 10) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.sendMultiMedia", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("multiMedia", String(describing: multiMedia)), ("scheduleDate", String(describing: scheduleDate)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, reaction: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(627641572) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.sendReaction", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("reaction", String(describing: reaction))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendScheduledMessages(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1120369398) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.sendScheduledMessages", parameters: [("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendScreenshotNotification(peer: Api.InputPeer, replyToMsgId: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-914493408) + peer.serialize(buffer, true) + serializeInt32(replyToMsgId, buffer: buffer, boxed: false) + serializeInt64(randomId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.sendScreenshotNotification", parameters: [("peer", String(describing: peer)), ("replyToMsgId", String(describing: replyToMsgId)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendVote(peer: Api.InputPeer, msgId: Int32, options: [Buffer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(283795844) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(options.count)) + for item in options { + serializeBytes(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.sendVote", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("options", String(describing: options))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendWebViewData(bot: Api.InputUser, randomId: Int64, buttonText: String, data: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-603831608) + bot.serialize(buffer, true) + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeString(buttonText, buffer: buffer, boxed: false) + serializeString(data, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.sendWebViewData", parameters: [("bot", String(describing: bot)), ("randomId", String(describing: randomId)), ("buttonText", String(describing: buttonText)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func sendWebViewResultMessage(botQueryId: String, result: Api.InputBotInlineResult) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(172168437) + serializeString(botQueryId, buffer: buffer, boxed: false) + result.serialize(buffer, true) + return (FunctionDescription(name: "messages.sendWebViewResultMessage", parameters: [("botQueryId", String(describing: botQueryId)), ("result", String(describing: result))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.WebViewMessageSent? in + let reader = BufferReader(buffer) + var result: Api.WebViewMessageSent? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.WebViewMessageSent + } + return result + }) + } +} +public extension Api.functions.messages { + static func setBotCallbackAnswer(flags: Int32, queryId: Int64, message: String?, url: String?, cacheTime: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-712043766) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(message!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(url!, buffer: buffer, boxed: false)} + serializeInt32(cacheTime, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setBotCallbackAnswer", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("message", String(describing: message)), ("url", String(describing: url)), ("cacheTime", String(describing: cacheTime))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setBotPrecheckoutResults(flags: Int32, queryId: Int64, error: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(163765653) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(error!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.setBotPrecheckoutResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("error", String(describing: error))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setBotShippingResults(flags: Int32, queryId: Int64, error: String?, shippingOptions: [Api.ShippingOption]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-436833542) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(error!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(shippingOptions!.count)) + for item in shippingOptions! { + item.serialize(buffer, true) + }} + return (FunctionDescription(name: "messages.setBotShippingResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("error", String(describing: error)), ("shippingOptions", String(describing: shippingOptions))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setChatAvailableReactions(peer: Api.InputPeer, availableReactions: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(335875750) + peer.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(availableReactions.count)) + for item in availableReactions { + serializeString(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func setChatTheme(peer: Api.InputPeer, emoticon: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-432283329) + peer.serialize(buffer, true) + serializeString(emoticon, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setChatTheme", parameters: [("peer", String(describing: peer)), ("emoticon", String(describing: emoticon))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func setDefaultReaction(reaction: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-647969580) + serializeString(reaction, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setDefaultReaction", parameters: [("reaction", String(describing: reaction))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setEncryptedTyping(peer: Api.InputEncryptedChat, typing: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2031374829) + peer.serialize(buffer, true) + typing.serialize(buffer, true) + return (FunctionDescription(name: "messages.setEncryptedTyping", parameters: [("peer", String(describing: peer)), ("typing", String(describing: typing))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setGameScore(flags: Int32, peer: Api.InputPeer, id: Int32, userId: Api.InputUser, score: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1896289088) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + serializeInt32(score, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setGameScore", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("score", String(describing: score))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func setHistoryTTL(peer: Api.InputPeer, period: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1207017500) + peer.serialize(buffer, true) + serializeInt32(period, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setHistoryTTL", parameters: [("peer", String(describing: peer)), ("period", String(describing: period))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func setInlineBotResults(flags: Int32, queryId: Int64, results: [Api.InputBotInlineResult], cacheTime: Int32, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-346119674) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(results.count)) + for item in results { + item.serialize(buffer, true) + } + serializeInt32(cacheTime, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 3) != 0 {switchPm!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.setInlineBotResults", parameters: [("flags", String(describing: flags)), ("queryId", String(describing: queryId)), ("results", String(describing: results)), ("cacheTime", String(describing: cacheTime)), ("nextOffset", String(describing: nextOffset)), ("switchPm", String(describing: switchPm))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setInlineGameScore(flags: Int32, id: Api.InputBotInlineMessageID, userId: Api.InputUser, score: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(363700068) + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + userId.serialize(buffer, true) + serializeInt32(score, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.setInlineGameScore", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("userId", String(describing: userId)), ("score", String(describing: score))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func setTyping(flags: Int32, peer: Api.InputPeer, topMsgId: Int32?, action: Api.SendMessageAction) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1486110434) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)} + action.serialize(buffer, true) + return (FunctionDescription(name: "messages.setTyping", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("topMsgId", String(describing: topMsgId)), ("action", String(describing: action))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func startBot(bot: Api.InputUser, peer: Api.InputPeer, randomId: Int64, startParam: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-421563528) + bot.serialize(buffer, true) + peer.serialize(buffer, true) + serializeInt64(randomId, buffer: buffer, boxed: false) + serializeString(startParam, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.startBot", parameters: [("bot", String(describing: bot)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("startParam", String(describing: startParam))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func startHistoryImport(peer: Api.InputPeer, importId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1271008444) + peer.serialize(buffer, true) + serializeInt64(importId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.startHistoryImport", parameters: [("peer", String(describing: peer)), ("importId", String(describing: importId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func toggleBotInAttachMenu(bot: Api.InputUser, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(451818415) + bot.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "messages.toggleBotInAttachMenu", parameters: [("bot", String(describing: bot)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func toggleDialogPin(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1489903017) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.toggleDialogPin", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func toggleNoForwards(peer: Api.InputPeer, enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1323389022) + peer.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "messages.toggleNoForwards", parameters: [("peer", String(describing: peer)), ("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func toggleStickerSets(flags: Int32, stickersets: [Api.InputStickerSet]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1257951254) + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stickersets.count)) + for item in stickersets { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "messages.toggleStickerSets", parameters: [("flags", String(describing: flags)), ("stickersets", String(describing: stickersets))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func transcribeAudio(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(647928393) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.transcribeAudio", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranscribedAudio? in + let reader = BufferReader(buffer) + var result: Api.messages.TranscribedAudio? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.TranscribedAudio + } + return result + }) + } +} +public extension Api.functions.messages { + static func translateText(flags: Int32, peer: Api.InputPeer?, msgId: Int32?, text: String?, fromLang: String?, toLang: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(617508334) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(msgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(text!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {serializeString(fromLang!, buffer: buffer, boxed: false)} + serializeString(toLang, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.translateText", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("text", String(describing: text)), ("fromLang", String(describing: fromLang)), ("toLang", String(describing: toLang))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.TranslatedText? in + let reader = BufferReader(buffer) + var result: Api.messages.TranslatedText? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.TranslatedText + } + return result + }) + } +} +public extension Api.functions.messages { + static func uninstallStickerSet(stickerset: Api.InputStickerSet) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-110209570) + stickerset.serialize(buffer, true) + return (FunctionDescription(name: "messages.uninstallStickerSet", parameters: [("stickerset", String(describing: stickerset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func unpinAllMessages(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-265962357) + peer.serialize(buffer, true) + return (FunctionDescription(name: "messages.unpinAllMessages", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} +public extension Api.functions.messages { + static func updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(450142282) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {filter!.serialize(buffer, true)} + return (FunctionDescription(name: "messages.updateDialogFilter", parameters: [("flags", String(describing: flags)), ("id", String(describing: id)), ("filter", String(describing: filter))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func updateDialogFiltersOrder(order: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-983318044) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "messages.updateDialogFiltersOrder", parameters: [("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.messages { + static func updatePinnedMessage(flags: Int32, peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-760547348) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.updatePinnedMessage", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.messages { + static func uploadEncryptedFile(peer: Api.InputEncryptedChat, file: Api.InputEncryptedFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1347929239) + peer.serialize(buffer, true) + file.serialize(buffer, true) + return (FunctionDescription(name: "messages.uploadEncryptedFile", parameters: [("peer", String(describing: peer)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.EncryptedFile? in + let reader = BufferReader(buffer) + var result: Api.EncryptedFile? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.EncryptedFile + } + return result + }) + } +} +public extension Api.functions.messages { + static func uploadImportedMedia(peer: Api.InputPeer, importId: Int64, fileName: String, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(713433234) + peer.serialize(buffer, true) + serializeInt64(importId, buffer: buffer, boxed: false) + serializeString(fileName, buffer: buffer, boxed: false) + media.serialize(buffer, true) + return (FunctionDescription(name: "messages.uploadImportedMedia", parameters: [("peer", String(describing: peer)), ("importId", String(describing: importId)), ("fileName", String(describing: fileName)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in + let reader = BufferReader(buffer) + var result: Api.MessageMedia? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + return result + }) + } +} +public extension Api.functions.messages { + static func uploadMedia(peer: Api.InputPeer, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1369162417) + peer.serialize(buffer, true) + media.serialize(buffer, true) + return (FunctionDescription(name: "messages.uploadMedia", parameters: [("peer", String(describing: peer)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in + let reader = BufferReader(buffer) + var result: Api.MessageMedia? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + return result + }) + } +} +public extension Api.functions.payments { + static func assignAppStoreTransaction(receipt: Buffer, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2131921795) + serializeBytes(receipt, buffer: buffer, boxed: false) + purpose.serialize(buffer, true) + return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("receipt", String(describing: receipt)), ("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.payments { + static func assignPlayMarketTransaction(receipt: Api.DataJSON, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-537046829) + receipt.serialize(buffer, true) + purpose.serialize(buffer, true) + return (FunctionDescription(name: "payments.assignPlayMarketTransaction", parameters: [("receipt", String(describing: receipt)), ("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.payments { + static func canPurchasePremium(purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1614700874) + purpose.serialize(buffer, true) + return (FunctionDescription(name: "payments.canPurchasePremium", parameters: [("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.payments { + static func clearSavedInfo(flags: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-667062079) + serializeInt32(flags, buffer: buffer, boxed: false) + return (FunctionDescription(name: "payments.clearSavedInfo", parameters: [("flags", String(describing: flags))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.payments { + static func exportInvoice(invoiceMedia: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(261206117) + invoiceMedia.serialize(buffer, true) + return (FunctionDescription(name: "payments.exportInvoice", parameters: [("invoiceMedia", String(describing: invoiceMedia))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.ExportedInvoice? in + let reader = BufferReader(buffer) + var result: Api.payments.ExportedInvoice? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.ExportedInvoice + } + return result + }) + } +} +public extension Api.functions.payments { + static func getBankCardData(number: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(779736953) + serializeString(number, buffer: buffer, boxed: false) + return (FunctionDescription(name: "payments.getBankCardData", parameters: [("number", String(describing: number))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.BankCardData? in + let reader = BufferReader(buffer) + var result: Api.payments.BankCardData? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.BankCardData + } + return result + }) + } +} +public extension Api.functions.payments { + static func getPaymentForm(flags: Int32, invoice: Api.InputInvoice, themeParams: Api.DataJSON?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(924093883) + serializeInt32(flags, buffer: buffer, boxed: false) + invoice.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {themeParams!.serialize(buffer, true)} + return (FunctionDescription(name: "payments.getPaymentForm", parameters: [("flags", String(describing: flags)), ("invoice", String(describing: invoice)), ("themeParams", String(describing: themeParams))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentForm? in + let reader = BufferReader(buffer) + var result: Api.payments.PaymentForm? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.PaymentForm + } + return result + }) + } +} +public extension Api.functions.payments { + static func getPaymentReceipt(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(611897804) + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "payments.getPaymentReceipt", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentReceipt? in + let reader = BufferReader(buffer) + var result: Api.payments.PaymentReceipt? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.PaymentReceipt + } + return result + }) + } +} +public extension Api.functions.payments { + static func getSavedInfo() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(578650699) + + return (FunctionDescription(name: "payments.getSavedInfo", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedInfo? in + let reader = BufferReader(buffer) + var result: Api.payments.SavedInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.SavedInfo + } + return result + }) + } +} +public extension Api.functions.payments { + static func requestRecurringPayment(userId: Api.InputUser, recurringInitCharge: String, invoiceMedia: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(342791565) + userId.serialize(buffer, true) + serializeString(recurringInitCharge, buffer: buffer, boxed: false) + invoiceMedia.serialize(buffer, true) + return (FunctionDescription(name: "payments.requestRecurringPayment", parameters: [("userId", String(describing: userId)), ("recurringInitCharge", String(describing: recurringInitCharge)), ("invoiceMedia", String(describing: invoiceMedia))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.payments { + static func sendPaymentForm(flags: Int32, formId: Int64, invoice: Api.InputInvoice, requestedInfoId: String?, shippingOptionId: String?, credentials: Api.InputPaymentCredentials, tipAmount: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(755192367) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(formId, buffer: buffer, boxed: false) + invoice.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {serializeString(requestedInfoId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeString(shippingOptionId!, buffer: buffer, boxed: false)} + credentials.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {serializeInt64(tipAmount!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "payments.sendPaymentForm", parameters: [("flags", String(describing: flags)), ("formId", String(describing: formId)), ("invoice", String(describing: invoice)), ("requestedInfoId", String(describing: requestedInfoId)), ("shippingOptionId", String(describing: shippingOptionId)), ("credentials", String(describing: credentials)), ("tipAmount", String(describing: tipAmount))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.PaymentResult? in + let reader = BufferReader(buffer) + var result: Api.payments.PaymentResult? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.PaymentResult + } + return result + }) + } +} +public extension Api.functions.payments { + static func validateRequestedInfo(flags: Int32, invoice: Api.InputInvoice, info: Api.PaymentRequestedInfo) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1228345045) + serializeInt32(flags, buffer: buffer, boxed: false) + invoice.serialize(buffer, true) + info.serialize(buffer, true) + return (FunctionDescription(name: "payments.validateRequestedInfo", parameters: [("flags", String(describing: flags)), ("invoice", String(describing: invoice)), ("info", String(describing: info))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.ValidatedRequestedInfo? in + let reader = BufferReader(buffer) + var result: Api.payments.ValidatedRequestedInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.payments.ValidatedRequestedInfo + } + return result + }) + } +} +public extension Api.functions.phone { + static func acceptCall(peer: Api.InputPhoneCall, gB: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1003664544) + peer.serialize(buffer, true) + serializeBytes(gB, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + return (FunctionDescription(name: "phone.acceptCall", parameters: [("peer", String(describing: peer)), ("gB", String(describing: gB)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in + let reader = BufferReader(buffer) + var result: Api.phone.PhoneCall? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall + } + return result + }) + } +} +public extension Api.functions.phone { + static func checkGroupCall(call: Api.InputGroupCall, sources: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) { + let buffer = Buffer() + buffer.appendInt32(-1248003721) + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sources.count)) + for item in sources { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription(name: "phone.checkGroupCall", parameters: [("call", String(describing: call)), ("sources", String(describing: sources))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int32]? in + let reader = BufferReader(buffer) + var result: [Int32]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } + return result + }) + } +} +public extension Api.functions.phone { + static func confirmCall(peer: Api.InputPhoneCall, gA: Buffer, keyFingerprint: Int64, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(788404002) + peer.serialize(buffer, true) + serializeBytes(gA, buffer: buffer, boxed: false) + serializeInt64(keyFingerprint, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + return (FunctionDescription(name: "phone.confirmCall", parameters: [("peer", String(describing: peer)), ("gA", String(describing: gA)), ("keyFingerprint", String(describing: keyFingerprint)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in + let reader = BufferReader(buffer) + var result: Api.phone.PhoneCall? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall + } + return result + }) + } +} +public extension Api.functions.phone { + static func createGroupCall(flags: Int32, peer: Api.InputPeer, randomId: Int32, title: String?, scheduleDate: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1221445336) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(randomId, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(scheduleDate!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "phone.createGroupCall", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("randomId", String(describing: randomId)), ("title", String(describing: title)), ("scheduleDate", String(describing: scheduleDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func discardCall(flags: Int32, peer: Api.InputPhoneCall, duration: Int32, reason: Api.PhoneCallDiscardReason, connectionId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1295269440) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(duration, buffer: buffer, boxed: false) + reason.serialize(buffer, true) + serializeInt64(connectionId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.discardCall", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("duration", String(describing: duration)), ("reason", String(describing: reason)), ("connectionId", String(describing: connectionId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func discardGroupCall(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2054648117) + call.serialize(buffer, true) + return (FunctionDescription(name: "phone.discardGroupCall", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func editGroupCallParticipant(flags: Int32, call: Api.InputGroupCall, participant: Api.InputPeer, muted: Api.Bool?, volume: Int32?, raiseHand: Api.Bool?, videoStopped: Api.Bool?, videoPaused: Api.Bool?, presentationPaused: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1524155713) + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + participant.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {muted!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(volume!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {raiseHand!.serialize(buffer, true)} + if Int(flags) & Int(1 << 3) != 0 {videoStopped!.serialize(buffer, true)} + if Int(flags) & Int(1 << 4) != 0 {videoPaused!.serialize(buffer, true)} + if Int(flags) & Int(1 << 5) != 0 {presentationPaused!.serialize(buffer, true)} + return (FunctionDescription(name: "phone.editGroupCallParticipant", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("participant", String(describing: participant)), ("muted", String(describing: muted)), ("volume", String(describing: volume)), ("raiseHand", String(describing: raiseHand)), ("videoStopped", String(describing: videoStopped)), ("videoPaused", String(describing: videoPaused)), ("presentationPaused", String(describing: presentationPaused))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func editGroupCallTitle(call: Api.InputGroupCall, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(480685066) + call.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.editGroupCallTitle", parameters: [("call", String(describing: call)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func exportGroupCallInvite(flags: Int32, call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-425040769) + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + return (FunctionDescription(name: "phone.exportGroupCallInvite", parameters: [("flags", String(describing: flags)), ("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.ExportedGroupCallInvite? in + let reader = BufferReader(buffer) + var result: Api.phone.ExportedGroupCallInvite? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.ExportedGroupCallInvite + } + return result + }) + } +} +public extension Api.functions.phone { + static func getCallConfig() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1430593449) + + return (FunctionDescription(name: "phone.getCallConfig", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.DataJSON? in + let reader = BufferReader(buffer) + var result: Api.DataJSON? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.DataJSON + } + return result + }) + } +} +public extension Api.functions.phone { + static func getGroupCall(call: Api.InputGroupCall, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(68699611) + call.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.getGroupCall", parameters: [("call", String(describing: call)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCall? in + let reader = BufferReader(buffer) + var result: Api.phone.GroupCall? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.GroupCall + } + return result + }) + } +} +public extension Api.functions.phone { + static func getGroupCallJoinAs(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-277077702) + peer.serialize(buffer, true) + return (FunctionDescription(name: "phone.getGroupCallJoinAs", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.JoinAsPeers? in + let reader = BufferReader(buffer) + var result: Api.phone.JoinAsPeers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.JoinAsPeers + } + return result + }) + } +} +public extension Api.functions.phone { + static func getGroupCallStreamChannels(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(447879488) + call.serialize(buffer, true) + return (FunctionDescription(name: "phone.getGroupCallStreamChannels", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCallStreamChannels? in + let reader = BufferReader(buffer) + var result: Api.phone.GroupCallStreamChannels? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.GroupCallStreamChannels + } + return result + }) + } +} +public extension Api.functions.phone { + static func getGroupCallStreamRtmpUrl(peer: Api.InputPeer, revoke: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-558650433) + peer.serialize(buffer, true) + revoke.serialize(buffer, true) + return (FunctionDescription(name: "phone.getGroupCallStreamRtmpUrl", parameters: [("peer", String(describing: peer)), ("revoke", String(describing: revoke))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupCallStreamRtmpUrl? in + let reader = BufferReader(buffer) + var result: Api.phone.GroupCallStreamRtmpUrl? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.GroupCallStreamRtmpUrl + } + return result + }) + } +} +public extension Api.functions.phone { + static func getGroupParticipants(call: Api.InputGroupCall, ids: [Api.InputPeer], sources: [Int32], offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-984033109) + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(ids.count)) + for item in ids { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(sources.count)) + for item in sources { + serializeInt32(item, buffer: buffer, boxed: false) + } + serializeString(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.getGroupParticipants", parameters: [("call", String(describing: call)), ("ids", String(describing: ids)), ("sources", String(describing: sources)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.GroupParticipants? in + let reader = BufferReader(buffer) + var result: Api.phone.GroupParticipants? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.GroupParticipants + } + return result + }) + } +} +public extension Api.functions.phone { + static func inviteToGroupCall(call: Api.InputGroupCall, users: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(2067345760) + call.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "phone.inviteToGroupCall", parameters: [("call", String(describing: call)), ("users", String(describing: users))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func joinGroupCall(flags: Int32, call: Api.InputGroupCall, joinAs: Api.InputPeer, inviteHash: String?, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1322057861) + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + joinAs.serialize(buffer, true) + if Int(flags) & Int(1 << 1) != 0 {serializeString(inviteHash!, buffer: buffer, boxed: false)} + params.serialize(buffer, true) + return (FunctionDescription(name: "phone.joinGroupCall", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinAs", String(describing: joinAs)), ("inviteHash", String(describing: inviteHash)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func joinGroupCallPresentation(call: Api.InputGroupCall, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-873829436) + call.serialize(buffer, true) + params.serialize(buffer, true) + return (FunctionDescription(name: "phone.joinGroupCallPresentation", parameters: [("call", String(describing: call)), ("params", String(describing: params))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func leaveGroupCall(call: Api.InputGroupCall, source: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1342404601) + call.serialize(buffer, true) + serializeInt32(source, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.leaveGroupCall", parameters: [("call", String(describing: call)), ("source", String(describing: source))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func leaveGroupCallPresentation(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(475058500) + call.serialize(buffer, true) + return (FunctionDescription(name: "phone.leaveGroupCallPresentation", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func receivedCall(peer: Api.InputPhoneCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(399855457) + peer.serialize(buffer, true) + return (FunctionDescription(name: "phone.receivedCall", parameters: [("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.phone { + static func requestCall(flags: Int32, userId: Api.InputUser, randomId: Int32, gAHash: Buffer, `protocol`: Api.PhoneCallProtocol) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1124046573) + serializeInt32(flags, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + serializeInt32(randomId, buffer: buffer, boxed: false) + serializeBytes(gAHash, buffer: buffer, boxed: false) + `protocol`.serialize(buffer, true) + return (FunctionDescription(name: "phone.requestCall", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("randomId", String(describing: randomId)), ("gAHash", String(describing: gAHash)), ("`protocol`", String(describing: `protocol`))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.phone.PhoneCall? in + let reader = BufferReader(buffer) + var result: Api.phone.PhoneCall? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.phone.PhoneCall + } + return result + }) + } +} +public extension Api.functions.phone { + static func saveCallDebug(peer: Api.InputPhoneCall, debug: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(662363518) + peer.serialize(buffer, true) + debug.serialize(buffer, true) + return (FunctionDescription(name: "phone.saveCallDebug", parameters: [("peer", String(describing: peer)), ("debug", String(describing: debug))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.phone { + static func saveCallLog(peer: Api.InputPhoneCall, file: Api.InputFile) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1092913030) + peer.serialize(buffer, true) + file.serialize(buffer, true) + return (FunctionDescription(name: "phone.saveCallLog", parameters: [("peer", String(describing: peer)), ("file", String(describing: file))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.phone { + static func saveDefaultGroupCallJoinAs(peer: Api.InputPeer, joinAs: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1465786252) + peer.serialize(buffer, true) + joinAs.serialize(buffer, true) + return (FunctionDescription(name: "phone.saveDefaultGroupCallJoinAs", parameters: [("peer", String(describing: peer)), ("joinAs", String(describing: joinAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.phone { + static func sendSignalingData(peer: Api.InputPhoneCall, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-8744061) + peer.serialize(buffer, true) + serializeBytes(data, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.sendSignalingData", parameters: [("peer", String(describing: peer)), ("data", String(describing: data))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.phone { + static func setCallRating(flags: Int32, peer: Api.InputPhoneCall, rating: Int32, comment: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1508562471) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(rating, buffer: buffer, boxed: false) + serializeString(comment, buffer: buffer, boxed: false) + return (FunctionDescription(name: "phone.setCallRating", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("rating", String(describing: rating)), ("comment", String(describing: comment))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func startScheduledGroupCall(call: Api.InputGroupCall) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1451287362) + call.serialize(buffer, true) + return (FunctionDescription(name: "phone.startScheduledGroupCall", parameters: [("call", String(describing: call))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func toggleGroupCallRecord(flags: Int32, call: Api.InputGroupCall, title: String?, videoPortrait: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-248985848) + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + if Int(flags) & Int(1 << 1) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 2) != 0 {videoPortrait!.serialize(buffer, true)} + return (FunctionDescription(name: "phone.toggleGroupCallRecord", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("title", String(describing: title)), ("videoPortrait", String(describing: videoPortrait))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func toggleGroupCallSettings(flags: Int32, call: Api.InputGroupCall, joinMuted: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1958458429) + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + if Int(flags) & Int(1 << 0) != 0 {joinMuted!.serialize(buffer, true)} + return (FunctionDescription(name: "phone.toggleGroupCallSettings", parameters: [("flags", String(describing: flags)), ("call", String(describing: call)), ("joinMuted", String(describing: joinMuted))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.phone { + static func toggleGroupCallStartSubscription(call: Api.InputGroupCall, subscribed: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(563885286) + call.serialize(buffer, true) + subscribed.serialize(buffer, true) + return (FunctionDescription(name: "phone.toggleGroupCallStartSubscription", parameters: [("call", String(describing: call)), ("subscribed", String(describing: subscribed))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } +} +public extension Api.functions.photos { + static func deletePhotos(id: [Api.InputPhoto]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int64]>) { + let buffer = Buffer() + buffer.appendInt32(-2016444625) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "photos.deletePhotos", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Int64]? in + let reader = BufferReader(buffer) + var result: [Int64]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + return result + }) + } +} +public extension Api.functions.photos { + static func getUserPhotos(userId: Api.InputUser, offset: Int32, maxId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1848823128) + userId.serialize(buffer, true) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt64(maxId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "photos.getUserPhotos", parameters: [("userId", String(describing: userId)), ("offset", String(describing: offset)), ("maxId", String(describing: maxId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photos? in + let reader = BufferReader(buffer) + var result: Api.photos.Photos? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.photos.Photos + } + return result + }) + } +} +public extension Api.functions.photos { + static func updateProfilePhoto(id: Api.InputPhoto) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1926525996) + id.serialize(buffer, true) + return (FunctionDescription(name: "photos.updateProfilePhoto", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in + let reader = BufferReader(buffer) + var result: Api.photos.Photo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.photos.Photo + } + return result + }) + } +} +public extension Api.functions.photos { + static func uploadProfilePhoto(flags: Int32, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1980559511) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)} + if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "photos.uploadProfilePhoto", parameters: [("flags", String(describing: flags)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in + let reader = BufferReader(buffer) + var result: Api.photos.Photo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.photos.Photo + } + return result + }) + } +} +public extension Api.functions.stats { + static func getBroadcastStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1421720550) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + return (FunctionDescription(name: "stats.getBroadcastStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.BroadcastStats? in + let reader = BufferReader(buffer) + var result: Api.stats.BroadcastStats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.stats.BroadcastStats + } + return result + }) + } +} +public extension Api.functions.stats { + static func getMegagroupStats(flags: Int32, channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-589330937) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + return (FunctionDescription(name: "stats.getMegagroupStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.MegagroupStats? in + let reader = BufferReader(buffer) + var result: Api.stats.MegagroupStats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.stats.MegagroupStats + } + return result + }) + } +} +public extension Api.functions.stats { + static func getMessagePublicForwards(channel: Api.InputChannel, msgId: Int32, offsetRate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1445996571) + channel.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt32(offsetRate, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stats.getMessagePublicForwards", parameters: [("channel", String(describing: channel)), ("msgId", String(describing: msgId)), ("offsetRate", String(describing: offsetRate)), ("offsetPeer", String(describing: offsetPeer)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } +} +public extension Api.functions.stats { + static func getMessageStats(flags: Int32, channel: Api.InputChannel, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1226791947) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stats.getMessageStats", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stats.MessageStats? in + let reader = BufferReader(buffer) + var result: Api.stats.MessageStats? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.stats.MessageStats + } + return result + }) + } +} +public extension Api.functions.stats { + static func loadAsyncGraph(flags: Int32, token: String, x: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1646092192) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(token, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt64(x!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "stats.loadAsyncGraph", parameters: [("flags", String(describing: flags)), ("token", String(describing: token)), ("x", String(describing: x))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StatsGraph? in + let reader = BufferReader(buffer) + var result: Api.StatsGraph? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.StatsGraph + } + return result + }) + } +} +public extension Api.functions.stickers { + static func addStickerToSet(stickerset: Api.InputStickerSet, sticker: Api.InputStickerSetItem) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-2041315650) + stickerset.serialize(buffer, true) + sticker.serialize(buffer, true) + return (FunctionDescription(name: "stickers.addStickerToSet", parameters: [("stickerset", String(describing: stickerset)), ("sticker", String(describing: sticker))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.stickers { + static func changeStickerPosition(sticker: Api.InputDocument, position: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-4795190) + sticker.serialize(buffer, true) + serializeInt32(position, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stickers.changeStickerPosition", parameters: [("sticker", String(describing: sticker)), ("position", String(describing: position))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.stickers { + static func checkShortName(shortName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(676017721) + serializeString(shortName, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stickers.checkShortName", parameters: [("shortName", String(describing: shortName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.stickers { + static func createStickerSet(flags: Int32, userId: Api.InputUser, title: String, shortName: String, thumb: Api.InputDocument?, stickers: [Api.InputStickerSetItem], software: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1876841625) + serializeInt32(flags, buffer: buffer, boxed: false) + userId.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + serializeString(shortName, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {thumb!.serialize(buffer, true)} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stickers.count)) + for item in stickers { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 3) != 0 {serializeString(software!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "stickers.createStickerSet", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("title", String(describing: title)), ("shortName", String(describing: shortName)), ("thumb", String(describing: thumb)), ("stickers", String(describing: stickers)), ("software", String(describing: software))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.stickers { + static func removeStickerFromSet(sticker: Api.InputDocument) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-143257775) + sticker.serialize(buffer, true) + return (FunctionDescription(name: "stickers.removeStickerFromSet", parameters: [("sticker", String(describing: sticker))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.stickers { + static func setStickerSetThumb(stickerset: Api.InputStickerSet, thumb: Api.InputDocument) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1707717072) + stickerset.serialize(buffer, true) + thumb.serialize(buffer, true) + return (FunctionDescription(name: "stickers.setStickerSetThumb", parameters: [("stickerset", String(describing: stickerset)), ("thumb", String(describing: thumb))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.StickerSet? in + let reader = BufferReader(buffer) + var result: Api.messages.StickerSet? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.StickerSet + } + return result + }) + } +} +public extension Api.functions.stickers { + static func suggestShortName(title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1303364867) + serializeString(title, buffer: buffer, boxed: false) + return (FunctionDescription(name: "stickers.suggestShortName", parameters: [("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stickers.SuggestedShortName? in + let reader = BufferReader(buffer) + var result: Api.stickers.SuggestedShortName? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.stickers.SuggestedShortName + } + return result + }) + } +} +public extension Api.functions.updates { + static func getChannelDifference(flags: Int32, channel: Api.InputChannel, filter: Api.ChannelMessagesFilter, pts: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(51854712) + serializeInt32(flags, buffer: buffer, boxed: false) + channel.serialize(buffer, true) + filter.serialize(buffer, true) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "updates.getChannelDifference", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("filter", String(describing: filter)), ("pts", String(describing: pts)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.ChannelDifference? in + let reader = BufferReader(buffer) + var result: Api.updates.ChannelDifference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.updates.ChannelDifference + } + return result + }) + } +} +public extension Api.functions.updates { + static func getDifference(flags: Int32, pts: Int32, ptsTotalLimit: Int32?, date: Int32, qts: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(630429265) + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ptsTotalLimit!, buffer: buffer, boxed: false)} + serializeInt32(date, buffer: buffer, boxed: false) + serializeInt32(qts, buffer: buffer, boxed: false) + return (FunctionDescription(name: "updates.getDifference", parameters: [("flags", String(describing: flags)), ("pts", String(describing: pts)), ("ptsTotalLimit", String(describing: ptsTotalLimit)), ("date", String(describing: date)), ("qts", String(describing: qts))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.Difference? in + let reader = BufferReader(buffer) + var result: Api.updates.Difference? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.updates.Difference + } + return result + }) + } +} +public extension Api.functions.updates { + static func getState() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-304838614) + + return (FunctionDescription(name: "updates.getState", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.updates.State? in + let reader = BufferReader(buffer) + var result: Api.updates.State? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.updates.State + } + return result + }) + } +} +public extension Api.functions.upload { + static func getCdnFile(fileToken: Buffer, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(962554330) + serializeBytes(fileToken, buffer: buffer, boxed: false) + serializeInt64(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.getCdnFile", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.CdnFile? in + let reader = BufferReader(buffer) + var result: Api.upload.CdnFile? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.upload.CdnFile + } + return result + }) + } +} +public extension Api.functions.upload { + static func getCdnFileHashes(fileToken: Buffer, offset: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { + let buffer = Buffer() + buffer.appendInt32(-1847836879) + serializeBytes(fileToken, buffer: buffer, boxed: false) + serializeInt64(offset, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.getCdnFileHashes", parameters: [("fileToken", String(describing: fileToken)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in + let reader = BufferReader(buffer) + var result: [Api.FileHash]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) + } + return result + }) + } +} +public extension Api.functions.upload { + static func getFile(flags: Int32, location: Api.InputFileLocation, offset: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1101843010) + serializeInt32(flags, buffer: buffer, boxed: false) + location.serialize(buffer, true) + serializeInt64(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.getFile", parameters: [("flags", String(describing: flags)), ("location", String(describing: location)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.File? in + let reader = BufferReader(buffer) + var result: Api.upload.File? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.upload.File + } + return result + }) + } +} +public extension Api.functions.upload { + static func getFileHashes(location: Api.InputFileLocation, offset: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { + let buffer = Buffer() + buffer.appendInt32(-1856595926) + location.serialize(buffer, true) + serializeInt64(offset, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.getFileHashes", parameters: [("location", String(describing: location)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in + let reader = BufferReader(buffer) + var result: [Api.FileHash]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) + } + return result + }) + } +} +public extension Api.functions.upload { + static func getWebFile(location: Api.InputWebFileLocation, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(619086221) + location.serialize(buffer, true) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.getWebFile", parameters: [("location", String(describing: location)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.upload.WebFile? in + let reader = BufferReader(buffer) + var result: Api.upload.WebFile? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.upload.WebFile + } + return result + }) + } +} +public extension Api.functions.upload { + static func reuploadCdnFile(fileToken: Buffer, requestToken: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.FileHash]>) { + let buffer = Buffer() + buffer.appendInt32(-1691921240) + serializeBytes(fileToken, buffer: buffer, boxed: false) + serializeBytes(requestToken, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.reuploadCdnFile", parameters: [("fileToken", String(describing: fileToken)), ("requestToken", String(describing: requestToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.FileHash]? in + let reader = BufferReader(buffer) + var result: [Api.FileHash]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.FileHash.self) + } + return result + }) + } +} +public extension Api.functions.upload { + static func saveBigFilePart(fileId: Int64, filePart: Int32, fileTotalParts: Int32, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-562337987) + serializeInt64(fileId, buffer: buffer, boxed: false) + serializeInt32(filePart, buffer: buffer, boxed: false) + serializeInt32(fileTotalParts, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.saveBigFilePart", parameters: [("fileId", String(describing: fileId)), ("filePart", String(describing: filePart)), ("fileTotalParts", String(describing: fileTotalParts)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.upload { + static func saveFilePart(fileId: Int64, filePart: Int32, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1291540959) + serializeInt64(fileId, buffer: buffer, boxed: false) + serializeInt32(filePart, buffer: buffer, boxed: false) + serializeBytes(bytes, buffer: buffer, boxed: false) + return (FunctionDescription(name: "upload.saveFilePart", parameters: [("fileId", String(describing: fileId)), ("filePart", String(describing: filePart)), ("bytes", String(describing: bytes))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} +public extension Api.functions.users { + static func getFullUser(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1240508136) + id.serialize(buffer, true) + return (FunctionDescription(name: "users.getFullUser", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.users.UserFull? in + let reader = BufferReader(buffer) + var result: Api.users.UserFull? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.users.UserFull + } + return result + }) + } +} +public extension Api.functions.users { + static func getUsers(id: [Api.InputUser]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.User]>) { + let buffer = Buffer() + buffer.appendInt32(227648840) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(id.count)) + for item in id { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "users.getUsers", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.User]? in + let reader = BufferReader(buffer) + var result: [Api.User]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + return result + }) + } +} +public extension Api.functions.users { + static func setSecureValueErrors(id: Api.InputUser, errors: [Api.SecureValueError]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1865902923) + id.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(errors.count)) + for item in errors { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "users.setSecureValueErrors", parameters: [("id", String(describing: id)), ("errors", String(describing: errors))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} diff --git a/submodules/TelegramApi/Sources/Api4.swift b/submodules/TelegramApi/Sources/Api4.swift index 17edf43042..666e1b148f 100644 --- a/submodules/TelegramApi/Sources/Api4.swift +++ b/submodules/TelegramApi/Sources/Api4.swift @@ -1202,6 +1202,7 @@ public extension Api { enum DocumentAttribute: TypeConstructorDescription { case documentAttributeAnimated case documentAttributeAudio(flags: Int32, duration: Int32, title: String?, performer: String?, waveform: Buffer?) + case documentAttributeCustomEmoji(flags: Int32, alt: String, stickerset: Api.InputStickerSet) case documentAttributeFilename(fileName: String) case documentAttributeHasStickers case documentAttributeImageSize(w: Int32, h: Int32) @@ -1226,6 +1227,14 @@ public extension Api { if Int(flags) & Int(1 << 1) != 0 {serializeString(performer!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 2) != 0 {serializeBytes(waveform!, buffer: buffer, boxed: false)} break + case .documentAttributeCustomEmoji(let flags, let alt, let stickerset): + if boxed { + buffer.appendInt32(-48981863) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(alt, buffer: buffer, boxed: false) + stickerset.serialize(buffer, true) + break case .documentAttributeFilename(let fileName): if boxed { buffer.appendInt32(358154344) @@ -1272,6 +1281,8 @@ public extension Api { return ("documentAttributeAnimated", []) case .documentAttributeAudio(let flags, let duration, let title, let performer, let waveform): return ("documentAttributeAudio", [("flags", String(describing: flags)), ("duration", String(describing: duration)), ("title", String(describing: title)), ("performer", String(describing: performer)), ("waveform", String(describing: waveform))]) + case .documentAttributeCustomEmoji(let flags, let alt, let stickerset): + return ("documentAttributeCustomEmoji", [("flags", String(describing: flags)), ("alt", String(describing: alt)), ("stickerset", String(describing: stickerset))]) case .documentAttributeFilename(let fileName): return ("documentAttributeFilename", [("fileName", String(describing: fileName))]) case .documentAttributeHasStickers: @@ -1311,6 +1322,25 @@ public extension Api { return nil } } + public static func parse_documentAttributeCustomEmoji(_ reader: BufferReader) -> DocumentAttribute? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: Api.InputStickerSet? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.InputStickerSet + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.DocumentAttribute.documentAttributeCustomEmoji(flags: _1!, alt: _2!, stickerset: _3!) + } + else { + return nil + } + } public static func parse_documentAttributeFilename(_ reader: BufferReader) -> DocumentAttribute? { var _1: String? _1 = parseString(reader) @@ -1386,85 +1416,3 @@ public extension Api { } } -public extension Api { - enum DraftMessage: TypeConstructorDescription { - case draftMessage(flags: Int32, replyToMsgId: Int32?, message: String, entities: [Api.MessageEntity]?, date: Int32) - case draftMessageEmpty(flags: Int32, date: Int32?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .draftMessage(let flags, let replyToMsgId, let message, let entities, let date): - if boxed { - buffer.appendInt32(-40996577) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} - serializeString(message, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(entities!.count)) - for item in entities! { - item.serialize(buffer, true) - }} - serializeInt32(date, buffer: buffer, boxed: false) - break - case .draftMessageEmpty(let flags, let date): - if boxed { - buffer.appendInt32(453805082) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(date!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .draftMessage(let flags, let replyToMsgId, let message, let entities, let date): - return ("draftMessage", [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("message", String(describing: message)), ("entities", String(describing: entities)), ("date", String(describing: date))]) - case .draftMessageEmpty(let flags, let date): - return ("draftMessageEmpty", [("flags", String(describing: flags)), ("date", String(describing: date))]) - } - } - - public static func parse_draftMessage(_ reader: BufferReader) -> DraftMessage? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - var _3: String? - _3 = parseString(reader) - var _4: [Api.MessageEntity]? - if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) - } } - var _5: Int32? - _5 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.DraftMessage.draftMessage(flags: _1!, replyToMsgId: _2, message: _3!, entities: _4, date: _5!) - } - else { - return nil - } - } - public static func parse_draftMessageEmpty(_ reader: BufferReader) -> DraftMessage? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil - if _c1 && _c2 { - return Api.DraftMessage.draftMessageEmpty(flags: _1!, date: _2) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api5.swift b/submodules/TelegramApi/Sources/Api5.swift index 1134cce7b5..1d06ca5338 100644 --- a/submodules/TelegramApi/Sources/Api5.swift +++ b/submodules/TelegramApi/Sources/Api5.swift @@ -1,3 +1,85 @@ +public extension Api { + enum DraftMessage: TypeConstructorDescription { + case draftMessage(flags: Int32, replyToMsgId: Int32?, message: String, entities: [Api.MessageEntity]?, date: Int32) + case draftMessageEmpty(flags: Int32, date: Int32?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .draftMessage(let flags, let replyToMsgId, let message, let entities, let date): + if boxed { + buffer.appendInt32(-40996577) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(replyToMsgId!, buffer: buffer, boxed: false)} + serializeString(message, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(entities!.count)) + for item in entities! { + item.serialize(buffer, true) + }} + serializeInt32(date, buffer: buffer, boxed: false) + break + case .draftMessageEmpty(let flags, let date): + if boxed { + buffer.appendInt32(453805082) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(date!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .draftMessage(let flags, let replyToMsgId, let message, let entities, let date): + return ("draftMessage", [("flags", String(describing: flags)), ("replyToMsgId", String(describing: replyToMsgId)), ("message", String(describing: message)), ("entities", String(describing: entities)), ("date", String(describing: date))]) + case .draftMessageEmpty(let flags, let date): + return ("draftMessageEmpty", [("flags", String(describing: flags)), ("date", String(describing: date))]) + } + } + + public static func parse_draftMessage(_ reader: BufferReader) -> DraftMessage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: String? + _3 = parseString(reader) + var _4: [Api.MessageEntity]? + if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + } } + var _5: Int32? + _5 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil + let _c5 = _5 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 { + return Api.DraftMessage.draftMessage(flags: _1!, replyToMsgId: _2, message: _3!, entities: _4, date: _5!) + } + else { + return nil + } + } + public static func parse_draftMessageEmpty(_ reader: BufferReader) -> DraftMessage? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + if _c1 && _c2 { + return Api.DraftMessage.draftMessageEmpty(flags: _1!, date: _2) + } + else { + return nil + } + } + + } +} public extension Api { enum EmojiKeyword: TypeConstructorDescription { case emojiKeyword(keyword: String, emoticons: [String]) @@ -1298,87 +1380,3 @@ public extension Api { } } -public extension Api { - enum HighScore: TypeConstructorDescription { - case highScore(pos: Int32, userId: Int64, score: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .highScore(let pos, let userId, let score): - if boxed { - buffer.appendInt32(1940093419) - } - serializeInt32(pos, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(score, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .highScore(let pos, let userId, let score): - return ("highScore", [("pos", String(describing: pos)), ("userId", String(describing: userId)), ("score", String(describing: score))]) - } - } - - public static func parse_highScore(_ reader: BufferReader) -> HighScore? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.HighScore.highScore(pos: _1!, userId: _2!, score: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum ImportedContact: TypeConstructorDescription { - case importedContact(userId: Int64, clientId: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .importedContact(let userId, let clientId): - if boxed { - buffer.appendInt32(-1052885936) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt64(clientId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .importedContact(let userId, let clientId): - return ("importedContact", [("userId", String(describing: userId)), ("clientId", String(describing: clientId))]) - } - } - - public static func parse_importedContact(_ reader: BufferReader) -> ImportedContact? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.ImportedContact.importedContact(userId: _1!, clientId: _2!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api6.swift b/submodules/TelegramApi/Sources/Api6.swift index 2696ebe04e..7201cfe85b 100644 --- a/submodules/TelegramApi/Sources/Api6.swift +++ b/submodules/TelegramApi/Sources/Api6.swift @@ -1,3 +1,87 @@ +public extension Api { + enum HighScore: TypeConstructorDescription { + case highScore(pos: Int32, userId: Int64, score: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .highScore(let pos, let userId, let score): + if boxed { + buffer.appendInt32(1940093419) + } + serializeInt32(pos, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(score, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .highScore(let pos, let userId, let score): + return ("highScore", [("pos", String(describing: pos)), ("userId", String(describing: userId)), ("score", String(describing: score))]) + } + } + + public static func parse_highScore(_ reader: BufferReader) -> HighScore? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.HighScore.highScore(pos: _1!, userId: _2!, score: _3!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum ImportedContact: TypeConstructorDescription { + case importedContact(userId: Int64, clientId: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .importedContact(let userId, let clientId): + if boxed { + buffer.appendInt32(-1052885936) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt64(clientId, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .importedContact(let userId, let clientId): + return ("importedContact", [("userId", String(describing: userId)), ("clientId", String(describing: clientId))]) + } + } + + public static func parse_importedContact(_ reader: BufferReader) -> ImportedContact? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.ImportedContact.importedContact(userId: _1!, clientId: _2!) + } + else { + return nil + } + } + + } +} public extension Api { enum InlineBotSwitchPM: TypeConstructorDescription { case inlineBotSwitchPM(text: String, startParam: String) @@ -1060,61 +1144,3 @@ public extension Api { } } -public extension Api { - enum InputDialogPeer: TypeConstructorDescription { - case inputDialogPeer(peer: Api.InputPeer) - case inputDialogPeerFolder(folderId: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputDialogPeer(let peer): - if boxed { - buffer.appendInt32(-55902537) - } - peer.serialize(buffer, true) - break - case .inputDialogPeerFolder(let folderId): - if boxed { - buffer.appendInt32(1684014375) - } - serializeInt32(folderId, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputDialogPeer(let peer): - return ("inputDialogPeer", [("peer", String(describing: peer))]) - case .inputDialogPeerFolder(let folderId): - return ("inputDialogPeerFolder", [("folderId", String(describing: folderId))]) - } - } - - public static func parse_inputDialogPeer(_ reader: BufferReader) -> InputDialogPeer? { - var _1: Api.InputPeer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputPeer - } - let _c1 = _1 != nil - if _c1 { - return Api.InputDialogPeer.inputDialogPeer(peer: _1!) - } - else { - return nil - } - } - public static func parse_inputDialogPeerFolder(_ reader: BufferReader) -> InputDialogPeer? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.InputDialogPeer.inputDialogPeerFolder(folderId: _1!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api7.swift b/submodules/TelegramApi/Sources/Api7.swift index ea95c104cb..761c268200 100644 --- a/submodules/TelegramApi/Sources/Api7.swift +++ b/submodules/TelegramApi/Sources/Api7.swift @@ -1,3 +1,61 @@ +public extension Api { + enum InputDialogPeer: TypeConstructorDescription { + case inputDialogPeer(peer: Api.InputPeer) + case inputDialogPeerFolder(folderId: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputDialogPeer(let peer): + if boxed { + buffer.appendInt32(-55902537) + } + peer.serialize(buffer, true) + break + case .inputDialogPeerFolder(let folderId): + if boxed { + buffer.appendInt32(1684014375) + } + serializeInt32(folderId, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputDialogPeer(let peer): + return ("inputDialogPeer", [("peer", String(describing: peer))]) + case .inputDialogPeerFolder(let folderId): + return ("inputDialogPeerFolder", [("folderId", String(describing: folderId))]) + } + } + + public static func parse_inputDialogPeer(_ reader: BufferReader) -> InputDialogPeer? { + var _1: Api.InputPeer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputPeer + } + let _c1 = _1 != nil + if _c1 { + return Api.InputDialogPeer.inputDialogPeer(peer: _1!) + } + else { + return nil + } + } + public static func parse_inputDialogPeerFolder(_ reader: BufferReader) -> InputDialogPeer? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.InputDialogPeer.inputDialogPeerFolder(folderId: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum InputDocument: TypeConstructorDescription { case inputDocument(id: Int64, accessHash: Int64, fileReference: Buffer) diff --git a/submodules/TelegramApi/Sources/Api8.swift b/submodules/TelegramApi/Sources/Api8.swift index 6fd500f79e..67d9f486fc 100644 --- a/submodules/TelegramApi/Sources/Api8.swift +++ b/submodules/TelegramApi/Sources/Api8.swift @@ -606,6 +606,7 @@ public extension Api { case inputPrivacyKeyPhoneP2P case inputPrivacyKeyProfilePhoto case inputPrivacyKeyStatusTimestamp + case inputPrivacyKeyVoiceMessages public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -656,6 +657,12 @@ public extension Api { buffer.appendInt32(1335282456) } + break + case .inputPrivacyKeyVoiceMessages: + if boxed { + buffer.appendInt32(-1360618136) + } + break } } @@ -678,6 +685,8 @@ public extension Api { return ("inputPrivacyKeyProfilePhoto", []) case .inputPrivacyKeyStatusTimestamp: return ("inputPrivacyKeyStatusTimestamp", []) + case .inputPrivacyKeyVoiceMessages: + return ("inputPrivacyKeyVoiceMessages", []) } } @@ -705,173 +714,8 @@ public extension Api { public static func parse_inputPrivacyKeyStatusTimestamp(_ reader: BufferReader) -> InputPrivacyKey? { return Api.InputPrivacyKey.inputPrivacyKeyStatusTimestamp } - - } -} -public extension Api { - enum InputPrivacyRule: TypeConstructorDescription { - case inputPrivacyValueAllowAll - case inputPrivacyValueAllowChatParticipants(chats: [Int64]) - case inputPrivacyValueAllowContacts - case inputPrivacyValueAllowUsers(users: [Api.InputUser]) - case inputPrivacyValueDisallowAll - case inputPrivacyValueDisallowChatParticipants(chats: [Int64]) - case inputPrivacyValueDisallowContacts - case inputPrivacyValueDisallowUsers(users: [Api.InputUser]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputPrivacyValueAllowAll: - if boxed { - buffer.appendInt32(407582158) - } - - break - case .inputPrivacyValueAllowChatParticipants(let chats): - if boxed { - buffer.appendInt32(-2079962673) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .inputPrivacyValueAllowContacts: - if boxed { - buffer.appendInt32(218751099) - } - - break - case .inputPrivacyValueAllowUsers(let users): - if boxed { - buffer.appendInt32(320652927) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - case .inputPrivacyValueDisallowAll: - if boxed { - buffer.appendInt32(-697604407) - } - - break - case .inputPrivacyValueDisallowChatParticipants(let chats): - if boxed { - buffer.appendInt32(-380694650) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - serializeInt64(item, buffer: buffer, boxed: false) - } - break - case .inputPrivacyValueDisallowContacts: - if boxed { - buffer.appendInt32(195371015) - } - - break - case .inputPrivacyValueDisallowUsers(let users): - if boxed { - buffer.appendInt32(-1877932953) - } - 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 .inputPrivacyValueAllowAll: - return ("inputPrivacyValueAllowAll", []) - case .inputPrivacyValueAllowChatParticipants(let chats): - return ("inputPrivacyValueAllowChatParticipants", [("chats", String(describing: chats))]) - case .inputPrivacyValueAllowContacts: - return ("inputPrivacyValueAllowContacts", []) - case .inputPrivacyValueAllowUsers(let users): - return ("inputPrivacyValueAllowUsers", [("users", String(describing: users))]) - case .inputPrivacyValueDisallowAll: - return ("inputPrivacyValueDisallowAll", []) - case .inputPrivacyValueDisallowChatParticipants(let chats): - return ("inputPrivacyValueDisallowChatParticipants", [("chats", String(describing: chats))]) - case .inputPrivacyValueDisallowContacts: - return ("inputPrivacyValueDisallowContacts", []) - case .inputPrivacyValueDisallowUsers(let users): - return ("inputPrivacyValueDisallowUsers", [("users", String(describing: users))]) - } - } - - public static func parse_inputPrivacyValueAllowAll(_ reader: BufferReader) -> InputPrivacyRule? { - return Api.InputPrivacyRule.inputPrivacyValueAllowAll - } - public static func parse_inputPrivacyValueAllowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.InputPrivacyRule.inputPrivacyValueAllowChatParticipants(chats: _1!) - } - else { - return nil - } - } - public static func parse_inputPrivacyValueAllowContacts(_ reader: BufferReader) -> InputPrivacyRule? { - return Api.InputPrivacyRule.inputPrivacyValueAllowContacts - } - public static func parse_inputPrivacyValueAllowUsers(_ reader: BufferReader) -> InputPrivacyRule? { - var _1: [Api.InputUser]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.InputPrivacyRule.inputPrivacyValueAllowUsers(users: _1!) - } - else { - return nil - } - } - public static func parse_inputPrivacyValueDisallowAll(_ reader: BufferReader) -> InputPrivacyRule? { - return Api.InputPrivacyRule.inputPrivacyValueDisallowAll - } - public static func parse_inputPrivacyValueDisallowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? { - var _1: [Int64]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.InputPrivacyRule.inputPrivacyValueDisallowChatParticipants(chats: _1!) - } - else { - return nil - } - } - public static func parse_inputPrivacyValueDisallowContacts(_ reader: BufferReader) -> InputPrivacyRule? { - return Api.InputPrivacyRule.inputPrivacyValueDisallowContacts - } - public static func parse_inputPrivacyValueDisallowUsers(_ reader: BufferReader) -> InputPrivacyRule? { - var _1: [Api.InputUser]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.InputPrivacyRule.inputPrivacyValueDisallowUsers(users: _1!) - } - else { - return nil - } + public static func parse_inputPrivacyKeyVoiceMessages(_ reader: BufferReader) -> InputPrivacyKey? { + return Api.InputPrivacyKey.inputPrivacyKeyVoiceMessages } } diff --git a/submodules/TelegramApi/Sources/Api9.swift b/submodules/TelegramApi/Sources/Api9.swift index fc80ab45ba..d7fa9c089c 100644 --- a/submodules/TelegramApi/Sources/Api9.swift +++ b/submodules/TelegramApi/Sources/Api9.swift @@ -1,3 +1,171 @@ +public extension Api { + enum InputPrivacyRule: TypeConstructorDescription { + case inputPrivacyValueAllowAll + case inputPrivacyValueAllowChatParticipants(chats: [Int64]) + case inputPrivacyValueAllowContacts + case inputPrivacyValueAllowUsers(users: [Api.InputUser]) + case inputPrivacyValueDisallowAll + case inputPrivacyValueDisallowChatParticipants(chats: [Int64]) + case inputPrivacyValueDisallowContacts + case inputPrivacyValueDisallowUsers(users: [Api.InputUser]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputPrivacyValueAllowAll: + if boxed { + buffer.appendInt32(407582158) + } + + break + case .inputPrivacyValueAllowChatParticipants(let chats): + if boxed { + buffer.appendInt32(-2079962673) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .inputPrivacyValueAllowContacts: + if boxed { + buffer.appendInt32(218751099) + } + + break + case .inputPrivacyValueAllowUsers(let users): + if boxed { + buffer.appendInt32(320652927) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + case .inputPrivacyValueDisallowAll: + if boxed { + buffer.appendInt32(-697604407) + } + + break + case .inputPrivacyValueDisallowChatParticipants(let chats): + if boxed { + buffer.appendInt32(-380694650) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + serializeInt64(item, buffer: buffer, boxed: false) + } + break + case .inputPrivacyValueDisallowContacts: + if boxed { + buffer.appendInt32(195371015) + } + + break + case .inputPrivacyValueDisallowUsers(let users): + if boxed { + buffer.appendInt32(-1877932953) + } + 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 .inputPrivacyValueAllowAll: + return ("inputPrivacyValueAllowAll", []) + case .inputPrivacyValueAllowChatParticipants(let chats): + return ("inputPrivacyValueAllowChatParticipants", [("chats", String(describing: chats))]) + case .inputPrivacyValueAllowContacts: + return ("inputPrivacyValueAllowContacts", []) + case .inputPrivacyValueAllowUsers(let users): + return ("inputPrivacyValueAllowUsers", [("users", String(describing: users))]) + case .inputPrivacyValueDisallowAll: + return ("inputPrivacyValueDisallowAll", []) + case .inputPrivacyValueDisallowChatParticipants(let chats): + return ("inputPrivacyValueDisallowChatParticipants", [("chats", String(describing: chats))]) + case .inputPrivacyValueDisallowContacts: + return ("inputPrivacyValueDisallowContacts", []) + case .inputPrivacyValueDisallowUsers(let users): + return ("inputPrivacyValueDisallowUsers", [("users", String(describing: users))]) + } + } + + public static func parse_inputPrivacyValueAllowAll(_ reader: BufferReader) -> InputPrivacyRule? { + return Api.InputPrivacyRule.inputPrivacyValueAllowAll + } + public static func parse_inputPrivacyValueAllowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPrivacyRule.inputPrivacyValueAllowChatParticipants(chats: _1!) + } + else { + return nil + } + } + public static func parse_inputPrivacyValueAllowContacts(_ reader: BufferReader) -> InputPrivacyRule? { + return Api.InputPrivacyRule.inputPrivacyValueAllowContacts + } + public static func parse_inputPrivacyValueAllowUsers(_ reader: BufferReader) -> InputPrivacyRule? { + var _1: [Api.InputUser]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPrivacyRule.inputPrivacyValueAllowUsers(users: _1!) + } + else { + return nil + } + } + public static func parse_inputPrivacyValueDisallowAll(_ reader: BufferReader) -> InputPrivacyRule? { + return Api.InputPrivacyRule.inputPrivacyValueDisallowAll + } + public static func parse_inputPrivacyValueDisallowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? { + var _1: [Int64]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPrivacyRule.inputPrivacyValueDisallowChatParticipants(chats: _1!) + } + else { + return nil + } + } + public static func parse_inputPrivacyValueDisallowContacts(_ reader: BufferReader) -> InputPrivacyRule? { + return Api.InputPrivacyRule.inputPrivacyValueDisallowContacts + } + public static func parse_inputPrivacyValueDisallowUsers(_ reader: BufferReader) -> InputPrivacyRule? { + var _1: [Api.InputUser]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPrivacyRule.inputPrivacyValueDisallowUsers(users: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum InputSecureFile: TypeConstructorDescription { case inputSecureFile(id: Int64, accessHash: Int64) @@ -233,6 +401,7 @@ public extension Api { case inputStickerSetDice(emoticon: String) case inputStickerSetEmpty case inputStickerSetID(id: Int64, accessHash: Int64) + case inputStickerSetPremiumGifts case inputStickerSetShortName(shortName: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -267,6 +436,12 @@ public extension Api { } serializeInt64(id, buffer: buffer, boxed: false) serializeInt64(accessHash, buffer: buffer, boxed: false) + break + case .inputStickerSetPremiumGifts: + if boxed { + buffer.appendInt32(-930399486) + } + break case .inputStickerSetShortName(let shortName): if boxed { @@ -289,6 +464,8 @@ public extension Api { return ("inputStickerSetEmpty", []) case .inputStickerSetID(let id, let accessHash): return ("inputStickerSetID", [("id", String(describing: id)), ("accessHash", String(describing: accessHash))]) + case .inputStickerSetPremiumGifts: + return ("inputStickerSetPremiumGifts", []) case .inputStickerSetShortName(let shortName): return ("inputStickerSetShortName", [("shortName", String(describing: shortName))]) } @@ -328,6 +505,9 @@ public extension Api { return nil } } + public static func parse_inputStickerSetPremiumGifts(_ reader: BufferReader) -> InputStickerSet? { + return Api.InputStickerSet.inputStickerSetPremiumGifts + } public static func parse_inputStickerSetShortName(_ reader: BufferReader) -> InputStickerSet? { var _1: String? _1 = parseString(reader) @@ -454,6 +634,72 @@ public extension Api { } } +public extension Api { + enum InputStorePaymentPurpose: TypeConstructorDescription { + case inputStorePaymentGiftPremium(userId: Api.InputUser, currency: String, amount: Int64) + case inputStorePaymentPremiumSubscription(flags: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputStorePaymentGiftPremium(let userId, let currency, let amount): + if boxed { + buffer.appendInt32(1634697192) + } + userId.serialize(buffer, true) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) + break + case .inputStorePaymentPremiumSubscription(let flags): + if boxed { + buffer.appendInt32(-1502273946) + } + serializeInt32(flags, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputStorePaymentGiftPremium(let userId, let currency, let amount): + return ("inputStorePaymentGiftPremium", [("userId", String(describing: userId)), ("currency", String(describing: currency)), ("amount", String(describing: amount))]) + case .inputStorePaymentPremiumSubscription(let flags): + return ("inputStorePaymentPremiumSubscription", [("flags", String(describing: flags))]) + } + } + + public static func parse_inputStorePaymentGiftPremium(_ reader: BufferReader) -> InputStorePaymentPurpose? { + var _1: Api.InputUser? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputUser + } + var _2: String? + _2 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.InputStorePaymentPurpose.inputStorePaymentGiftPremium(userId: _1!, currency: _2!, amount: _3!) + } + else { + return nil + } + } + public static func parse_inputStorePaymentPremiumSubscription(_ reader: BufferReader) -> InputStorePaymentPurpose? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.InputStorePaymentPurpose.inputStorePaymentPremiumSubscription(flags: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum InputTheme: TypeConstructorDescription { case inputTheme(id: Int64, accessHash: Int64) @@ -760,391 +1006,3 @@ public extension Api { } } -public extension Api { - enum InputWebDocument: TypeConstructorDescription { - case inputWebDocument(url: String, size: Int32, mimeType: String, attributes: [Api.DocumentAttribute]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputWebDocument(let url, let size, let mimeType, let attributes): - if boxed { - buffer.appendInt32(-1678949555) - } - serializeString(url, buffer: buffer, boxed: false) - serializeInt32(size, buffer: buffer, boxed: false) - serializeString(mimeType, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(attributes.count)) - for item in attributes { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputWebDocument(let url, let size, let mimeType, let attributes): - return ("inputWebDocument", [("url", String(describing: url)), ("size", String(describing: size)), ("mimeType", String(describing: mimeType)), ("attributes", String(describing: attributes))]) - } - } - - public static func parse_inputWebDocument(_ reader: BufferReader) -> InputWebDocument? { - var _1: String? - _1 = parseString(reader) - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: [Api.DocumentAttribute]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.InputWebDocument.inputWebDocument(url: _1!, size: _2!, mimeType: _3!, attributes: _4!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum InputWebFileLocation: TypeConstructorDescription { - case inputWebFileGeoPointLocation(geoPoint: Api.InputGeoPoint, accessHash: Int64, w: Int32, h: Int32, zoom: Int32, scale: Int32) - case inputWebFileLocation(url: String, accessHash: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale): - if boxed { - buffer.appendInt32(-1625153079) - } - geoPoint.serialize(buffer, true) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeInt32(w, buffer: buffer, boxed: false) - serializeInt32(h, buffer: buffer, boxed: false) - serializeInt32(zoom, buffer: buffer, boxed: false) - serializeInt32(scale, buffer: buffer, boxed: false) - break - case .inputWebFileLocation(let url, let accessHash): - if boxed { - buffer.appendInt32(-1036396922) - } - serializeString(url, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputWebFileGeoPointLocation(let geoPoint, let accessHash, let w, let h, let zoom, let scale): - return ("inputWebFileGeoPointLocation", [("geoPoint", String(describing: geoPoint)), ("accessHash", String(describing: accessHash)), ("w", String(describing: w)), ("h", String(describing: h)), ("zoom", String(describing: zoom)), ("scale", String(describing: scale))]) - case .inputWebFileLocation(let url, let accessHash): - return ("inputWebFileLocation", [("url", String(describing: url)), ("accessHash", String(describing: accessHash))]) - } - } - - public static func parse_inputWebFileGeoPointLocation(_ reader: BufferReader) -> InputWebFileLocation? { - var _1: Api.InputGeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint - } - var _2: Int64? - _2 = reader.readInt64() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - _5 = reader.readInt32() - var _6: Int32? - _6 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.InputWebFileLocation.inputWebFileGeoPointLocation(geoPoint: _1!, accessHash: _2!, w: _3!, h: _4!, zoom: _5!, scale: _6!) - } - else { - return nil - } - } - public static func parse_inputWebFileLocation(_ reader: BufferReader) -> InputWebFileLocation? { - var _1: String? - _1 = parseString(reader) - var _2: Int64? - _2 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.InputWebFileLocation.inputWebFileLocation(url: _1!, accessHash: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum Invoice: TypeConstructorDescription { - case invoice(flags: Int32, currency: String, prices: [Api.LabeledPrice], maxTipAmount: Int64?, suggestedTipAmounts: [Int64]?, recurringTermsUrl: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .invoice(let flags, let currency, let prices, let maxTipAmount, let suggestedTipAmounts, let recurringTermsUrl): - if boxed { - buffer.appendInt32(1048946971) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(currency, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(prices.count)) - for item in prices { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 8) != 0 {serializeInt64(maxTipAmount!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 8) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(suggestedTipAmounts!.count)) - for item in suggestedTipAmounts! { - serializeInt64(item, buffer: buffer, boxed: false) - }} - if Int(flags) & Int(1 << 9) != 0 {serializeString(recurringTermsUrl!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .invoice(let flags, let currency, let prices, let maxTipAmount, let suggestedTipAmounts, let recurringTermsUrl): - return ("invoice", [("flags", String(describing: flags)), ("currency", String(describing: currency)), ("prices", String(describing: prices)), ("maxTipAmount", String(describing: maxTipAmount)), ("suggestedTipAmounts", String(describing: suggestedTipAmounts)), ("recurringTermsUrl", String(describing: recurringTermsUrl))]) - } - } - - public static func parse_invoice(_ reader: BufferReader) -> Invoice? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: [Api.LabeledPrice]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.LabeledPrice.self) - } - var _4: Int64? - if Int(_1!) & Int(1 << 8) != 0 {_4 = reader.readInt64() } - var _5: [Int64]? - if Int(_1!) & Int(1 << 8) != 0 {if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self) - } } - var _6: String? - if Int(_1!) & Int(1 << 9) != 0 {_6 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 8) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 8) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 9) == 0) || _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.Invoice.invoice(flags: _1!, currency: _2!, prices: _3!, maxTipAmount: _4, suggestedTipAmounts: _5, recurringTermsUrl: _6) - } - else { - return nil - } - } - - } -} -public extension Api { - enum JSONObjectValue: TypeConstructorDescription { - case jsonObjectValue(key: String, value: Api.JSONValue) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .jsonObjectValue(let key, let value): - if boxed { - buffer.appendInt32(-1059185703) - } - serializeString(key, buffer: buffer, boxed: false) - value.serialize(buffer, true) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .jsonObjectValue(let key, let value): - return ("jsonObjectValue", [("key", String(describing: key)), ("value", String(describing: value))]) - } - } - - public static func parse_jsonObjectValue(_ reader: BufferReader) -> JSONObjectValue? { - var _1: String? - _1 = parseString(reader) - var _2: Api.JSONValue? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.JSONValue - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.JSONObjectValue.jsonObjectValue(key: _1!, value: _2!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum JSONValue: TypeConstructorDescription { - case jsonArray(value: [Api.JSONValue]) - case jsonBool(value: Api.Bool) - case jsonNull - case jsonNumber(value: Double) - case jsonObject(value: [Api.JSONObjectValue]) - case jsonString(value: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .jsonArray(let value): - if boxed { - buffer.appendInt32(-146520221) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(value.count)) - for item in value { - item.serialize(buffer, true) - } - break - case .jsonBool(let value): - if boxed { - buffer.appendInt32(-952869270) - } - value.serialize(buffer, true) - break - case .jsonNull: - if boxed { - buffer.appendInt32(1064139624) - } - - break - case .jsonNumber(let value): - if boxed { - buffer.appendInt32(736157604) - } - serializeDouble(value, buffer: buffer, boxed: false) - break - case .jsonObject(let value): - if boxed { - buffer.appendInt32(-1715350371) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(value.count)) - for item in value { - item.serialize(buffer, true) - } - break - case .jsonString(let value): - if boxed { - buffer.appendInt32(-1222740358) - } - serializeString(value, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .jsonArray(let value): - return ("jsonArray", [("value", String(describing: value))]) - case .jsonBool(let value): - return ("jsonBool", [("value", String(describing: value))]) - case .jsonNull: - return ("jsonNull", []) - case .jsonNumber(let value): - return ("jsonNumber", [("value", String(describing: value))]) - case .jsonObject(let value): - return ("jsonObject", [("value", String(describing: value))]) - case .jsonString(let value): - return ("jsonString", [("value", String(describing: value))]) - } - } - - public static func parse_jsonArray(_ reader: BufferReader) -> JSONValue? { - var _1: [Api.JSONValue]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONValue.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.JSONValue.jsonArray(value: _1!) - } - else { - return nil - } - } - public static func parse_jsonBool(_ reader: BufferReader) -> JSONValue? { - var _1: Api.Bool? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Bool - } - let _c1 = _1 != nil - if _c1 { - return Api.JSONValue.jsonBool(value: _1!) - } - else { - return nil - } - } - public static func parse_jsonNull(_ reader: BufferReader) -> JSONValue? { - return Api.JSONValue.jsonNull - } - public static func parse_jsonNumber(_ reader: BufferReader) -> JSONValue? { - var _1: Double? - _1 = reader.readDouble() - let _c1 = _1 != nil - if _c1 { - return Api.JSONValue.jsonNumber(value: _1!) - } - else { - return nil - } - } - public static func parse_jsonObject(_ reader: BufferReader) -> JSONValue? { - var _1: [Api.JSONObjectValue]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.JSONObjectValue.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.JSONValue.jsonObject(value: _1!) - } - else { - return nil - } - } - public static func parse_jsonString(_ reader: BufferReader) -> JSONValue? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.JSONValue.jsonString(value: _1!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramCallsUI/Sources/CallRatingController.swift b/submodules/TelegramCallsUI/Sources/CallRatingController.swift index 82e0a51828..094191b079 100644 --- a/submodules/TelegramCallsUI/Sources/CallRatingController.swift +++ b/submodules/TelegramCallsUI/Sources/CallRatingController.swift @@ -292,7 +292,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int let name = "\(callId.id)_\(callId.accessHash).log.json" let path = callLogsPath(account: engine.account) + "/" + name let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)]) - let message = EnqueueMessage.message(text: comment, attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) return rate |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [message]) |> mapToSignal({ _ -> Signal in @@ -300,7 +300,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int })) } else if !comment.isEmpty { return rate - |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + |> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> mapToSignal({ _ -> Signal in return .single(Void()) })) diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index 930de2caa4..0d65d07d55 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -800,13 +800,13 @@ public final class MediaStreamComponent: CombinedComponent { AnyComponentWithIdentity(id: "a", component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: "anim_profilemore", - colors: [ - "Point 2.Group 1.Fill 1": whiteColor, - "Point 3.Group 1.Fill 1": whiteColor, - "Point 1.Group 1.Fill 1": whiteColor - ], - mode: .still + mode: .still(position: .begin) ), + colors: [ + "Point 2.Group 1.Fill 1": whiteColor, + "Point 3.Group 1.Fill 1": whiteColor, + "Point 1.Group 1.Fill 1": whiteColor + ], size: CGSize(width: 22.0, height: 22.0) ).tagged(moreAnimationTag))), ])), @@ -1190,8 +1190,21 @@ public final class MediaStreamComponentController: ViewControllerComponentContai view.expandFromPictureInPicture() } + if let validLayout = self.validLayout { + self.view.clipsToBounds = true + self.view.layer.cornerRadius = validLayout.deviceMetrics.screenCornerRadius + if #available(iOS 13.0, *) { + self.view.layer.cornerCurve = .continuous + } + + self.view.layer.animatePosition(from: CGPoint(x: self.view.frame.width * 0.9, y: 117.0), to: self.view.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { [weak self] _ in + self?.view.layer.cornerRadius = 0.0 + }) + self.view.layer.animateScale(from: 0.001, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + } + self.view.layer.allowsGroupOpacity = true - self.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { [weak self] _ in + self.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak self] _ in guard let strongSelf = self else { return } @@ -1226,6 +1239,18 @@ public final class MediaStreamComponentController: ViewControllerComponentContai strongSelf.view.layer.allowsGroupOpacity = false strongSelf.dismissImpl(completion: completion) }) + + if let validLayout = self.validLayout { + self.view.clipsToBounds = true + self.view.layer.cornerRadius = validLayout.deviceMetrics.screenCornerRadius + if #available(iOS 13.0, *) { + self.view.layer.cornerCurve = .continuous + } + + self.view.layer.animatePosition(from: self.view.center, to: CGPoint(x: self.view.frame.width * 0.9, y: 117.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in + }) + self.view.layer.animateScale(from: 1.0, to: 0.001, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + } } private func dismissImpl(completion: (() -> Void)? = nil) { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index f80cd6b9ee..bc3e5f39ad 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1264,7 +1264,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController dismissController?() if let strongSelf = self { - let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self { strongSelf.presentUndoOverlay(content: .forward(savedMessages: false, text: strongSelf.presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return true }) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift index 8019bfe7a7..7e3d8915e3 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift @@ -362,7 +362,7 @@ public final class VoiceChatJoinScreen: ViewController { let animation = contentNode.layer.makeAnimation(from: 0.0 as NSNumber, to: 1.0 as NSNumber, keyPath: "opacity", timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, duration: 0.35) animation.fillMode = .both if !fastOut { - animation.beginTime = CACurrentMediaTime() + 0.1 + animation.beginTime = contentNode.layer.convertTime(CACurrentMediaTime(), from: nil) + 0.1 } contentNode.layer.add(animation, forKey: "opacity") diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatTitleEditController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatTitleEditController.swift index f558c9f634..4aee77ae3c 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatTitleEditController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatTitleEditController.swift @@ -460,7 +460,7 @@ func voiceChatTitleEditController(sharedContext: SharedAccountContext, account: controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.inputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller, weak contentNode] animated in @@ -758,7 +758,7 @@ func voiceChatUserNameController(sharedContext: SharedAccountContext, account: A contentNode?.firstNameInputFieldNode.updateTheme(presentationData.theme) contentNode?.lastNameInputFieldNode.updateTheme(presentationData.theme) }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() } dismissImpl = { [weak controller, weak contentNode] animated in diff --git a/submodules/TelegramCore/Sources/Account/Account.swift b/submodules/TelegramCore/Sources/Account/Account.swift index 39dc7502c4..7d21c9bddd 100644 --- a/submodules/TelegramCore/Sources/Account/Account.swift +++ b/submodules/TelegramCore/Sources/Account/Account.swift @@ -1078,6 +1078,7 @@ public class Account { self.managedOperationsDisposable.add(managedSynchronizeGroupedPeersOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedSynchronizeInstalledStickerPacksOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager, namespace: .stickers).start()) self.managedOperationsDisposable.add(managedSynchronizeInstalledStickerPacksOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager, namespace: .masks).start()) + self.managedOperationsDisposable.add(managedSynchronizeInstalledStickerPacksOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager, namespace: .emoji).start()) self.managedOperationsDisposable.add(managedSynchronizeMarkFeaturedStickerPacksAsSeenOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedSynchronizeRecentlyUsedMediaOperations(postbox: self.postbox, network: self.network, category: .stickers, revalidationContext: self.mediaReferenceRevalidationContext).start()) self.managedOperationsDisposable.add(managedSynchronizeSavedGifsOperations(postbox: self.postbox, network: self.network, revalidationContext: self.mediaReferenceRevalidationContext).start()) diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 12a65b62e0..6427a34b34 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -201,7 +201,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] { } switch action { - case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe: + case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium: break case let .messageActionChannelMigrateFrom(_, chatId): result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId))) @@ -374,8 +374,8 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BankCard)) case let .messageEntitySpoiler(offset, length): result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Spoiler)) - /*case let .messageEntityAnimatedEmoji(offset, length): - result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .AnimatedEmoji(nil)))*/ + case let .messageEntityCustomEmoji(offset, length, documentId): + result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .CustomEmoji(stickerPack: nil, fileId: documentId))) } } return result diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift index cd4492c8cb..19a12ad360 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift @@ -85,6 +85,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe return TelegramMediaAction(action: .joinedByRequest) case let .messageActionWebViewDataSentMe(text, _), let .messageActionWebViewDataSent(text): return TelegramMediaAction(action: .webViewData(text)) + case let .messageActionGiftPremium(currency, amount, months): + return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, months: months)) } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index e8517f499d..4cea03247a 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift @@ -62,6 +62,8 @@ extension StickerPackReference { self = .dice(emoticon) case .inputStickerSetAnimatedEmojiAnimations: self = .animatedEmojiAnimations + case .inputStickerSetPremiumGifts: + self = .premiumGifts } } } @@ -102,6 +104,9 @@ func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAtt let isVoice = (flags & (1 << 10)) != 0 let waveformBuffer: Data? = waveform?.makeData() result.append(.Audio(isVoice: isVoice, duration: Int(duration), title: title, performer: performer, waveform: waveformBuffer)) + case let .documentAttributeCustomEmoji(flags, alt, stickerSet): + let isFree = (flags & (1 << 0)) != 0 + result.append(.CustomEmoji(isPremium: !isFree, alt: alt, packReference: StickerPackReference(apiInputSet: stickerSet))) } } return result diff --git a/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift index 25da7187cb..85014d0805 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift @@ -48,9 +48,8 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa apiEntities.append(.messageEntityBankCard(offset: offset, length: length)) case .Spoiler: apiEntities.append(.messageEntitySpoiler(offset: offset, length: length)) - case .AnimatedEmoji: - //apiEntities.append(.messageEntityAnimatedEmoji(offset: offset, length: length)) - break + case let .CustomEmoji(_, fileId): + apiEntities.append(.messageEntityCustomEmoji(offset: offset, length: length, documentId: fileId)) case .Custom: break } diff --git a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift index aa1e63dd32..d29e251724 100644 --- a/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift +++ b/submodules/TelegramCore/Sources/Network/FetchedMediaResource.swift @@ -1,7 +1,7 @@ import Foundation import Postbox import SwiftSignalKit - +import TelegramApi extension MediaResourceReference { var apiFileReference: Data? { @@ -227,6 +227,7 @@ private enum MediaReferenceRevalidationKey: Hashable { case peerAvatars(peer: PeerReference) case attachBot(peer: PeerReference) case notificationSoundList + case customEmoji(fileId: Int64) } private final class MediaReferenceRevalidationItemContext { @@ -391,6 +392,26 @@ final class MediaReferenceRevalidationContext { } } + func customEmoji(postbox: Postbox, network: Network, background: Bool, fileId: Int64) -> Signal { + return network.request(Api.functions.messages.getCustomEmojiDocuments(documentId: [fileId])) + |> map(Optional.init) + |> `catch` { _ -> Signal<[Api.Document]?, NoError> in + return .single(nil) + } + |> castError(RevalidateMediaReferenceError.self) + |> mapToSignal { result -> Signal in + guard let result = result else { + return .fail(.generic) + } + for document in result { + if let file = telegramMediaFileFromApiDocument(document) { + return .single(file) + } + } + return .fail(.generic) + } + } + func webPage(postbox: Postbox, network: Network, background: Bool, webPage: WebpageReference) -> Signal { return self.genericItem(key: .webPage(webPage: webPage), background: background, request: { next, error in return (updatedRemoteWebpage(postbox: postbox, network: network, webPage: webPage) @@ -726,7 +747,37 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali } } return .fail(.generic) - } + case let .customEmoji(media): + if let file = media as? TelegramMediaFile { + return revalidationContext.customEmoji(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, fileId: file.fileId.id) + |> mapToSignal { result -> Signal in + if let updatedResource = findUpdatedMediaResource(media: result, previousMedia: media, resource: resource) { + return postbox.transaction { transaction -> RevalidatedMediaResource in + if let id = media.id { + var attributes = result.attributes + if !attributes.contains(where: { attribute in + if case .hintIsValidated = attribute { + return true + } else { + return false + } + }) { + attributes.append(.hintIsValidated) + } + let file = result.withUpdatedAttributes(attributes) + updateMessageMedia(transaction: transaction, id: id, media: file) + } + return RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil) + } + |> castError(RevalidateMediaReferenceError.self) + } else { + return .fail(.generic) + } + } + } else { + return .fail(.generic) + } + } case let .avatar(peer, _): return revalidationContext.peer(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer) |> mapToSignal { updatedPeer -> Signal in diff --git a/submodules/TelegramCore/Sources/Network/MultipartFetch.swift b/submodules/TelegramCore/Sources/Network/MultipartFetch.swift index ebe9762f3f..52387c90db 100644 --- a/submodules/TelegramCore/Sources/Network/MultipartFetch.swift +++ b/submodules/TelegramCore/Sources/Network/MultipartFetch.swift @@ -591,6 +591,10 @@ private final class MultipartFetchManager { if totalTime > 0.0 { let speed = Double(totalByteCount) / totalTime Logger.shared.log("MultipartFetch", "\(self.resource.id.stringRepresentation) \(speed) bytes/s") + + #if DEBUG + self.checkState() + #endif } } } diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index e37d1f813f..d2b70fb1e6 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -9,47 +9,47 @@ public enum EnqueueMessageGrouping { } public enum EnqueueMessage { - case message(text: String, attributes: [MessageAttribute], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?) + case message(text: String, attributes: [MessageAttribute], inlineStickers: [MediaId: Media], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?) case forward(source: MessageId, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute], correlationId: Int64?) public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage { switch self { - case let .message(text, attributes, mediaReference, _, localGroupingKey, correlationId): - return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) - case .forward: - return self + case let .message(text, attributes, inlineStickers, mediaReference, _, localGroupingKey, correlationId): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + case .forward: + return self } } public func withUpdatedAttributes(_ f: ([MessageAttribute]) -> [MessageAttribute]) -> EnqueueMessage { switch self { - case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId): - return .message(text: text, attributes: f(attributes), mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) - case let .forward(source, grouping, attributes, correlationId): - return .forward(source: source, grouping: grouping, attributes: f(attributes), correlationId: correlationId) + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): + return .message(text: text, attributes: f(attributes), inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + case let .forward(source, grouping, attributes, correlationId): + return .forward(source: source, grouping: grouping, attributes: f(attributes), correlationId: correlationId) } } public func withUpdatedGroupingKey(_ f: (Int64?) -> Int64?) -> EnqueueMessage { switch self { - case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId): - return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId) - case .forward: - return self + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId) + case .forward: + return self } } public func withUpdatedCorrelationId(_ value: Int64?) -> EnqueueMessage { switch self { - case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, _): - return .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value) - case let .forward(source, grouping, attributes, _): - return .forward(source: source, grouping: grouping, attributes: attributes, correlationId: value) + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _): + return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value) + case let .forward(source, grouping, attributes, _): + return .forward(source: source, grouping: grouping, attributes: attributes, correlationId: value) } } public var groupingKey: Int64? { - if case let .message(_, _, _, _, localGroupingKey, _) = self { + if case let .message(_, _, _, _, _, localGroupingKey, _) = self { return localGroupingKey } else { return nil @@ -60,7 +60,7 @@ public enum EnqueueMessage { private extension EnqueueMessage { var correlationId: Int64? { switch self { - case let .message(_, _, _, _, _, correlationId): + case let .message(_, _, _, _, _, _, correlationId): return correlationId case let .forward(_, _, _, correlationId): return correlationId @@ -179,7 +179,7 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox: var hasMedia = false loop: for message in messages { switch message { - case let .message(_, _, mediaReference, _, _, _): + case let .message(_, _, _, mediaReference, _, _, _): if mediaReference != nil { hasMedia = true break loop @@ -196,14 +196,14 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox: var signals: [Signal<(Bool, EnqueueMessage), NoError>] = [] for message in messages { switch message { - case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId): + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): if let mediaReference = mediaReference { signals.append(opportunisticallyTransformMessageWithMedia(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, mediaReference: mediaReference, userInteractive: userInteractive) |> map { result -> (Bool, EnqueueMessage) in if let result = result { - return (true, .message(text: text, attributes: attributes, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) + return (true, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) } else { - return (false, .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) + return (false, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId)) } }) } else { @@ -275,7 +275,7 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal< } } - messages.append(.message(text: message.text, attributes: filteredAttributes, mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil)) + messages.append(.message(text: message.text, attributes: filteredAttributes, inlineStickers: [:], mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil)) } } let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: messages.map { (false, $0) }) @@ -305,7 +305,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } } switch message { - case let .message(_, attributes, _, replyToMessageId, _, _): + case let .message(_, attributes, _, _, replyToMessageId, _, _): if let replyToMessageId = replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) { var canBeForwarded = true if replyMessage.id.namespace != Namespaces.Message.Cloud { @@ -329,7 +329,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, mediaReference = .standalone(media: media) } } - updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))) + updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))) continue outer } } @@ -351,6 +351,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } var addedHashtags: [String] = [] + var emojiItems: [RecentEmojiItem] = [] var localGroupingKeyBySourceKey: [Int64: Int64] = [:] @@ -370,7 +371,11 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, globallyUniqueIds.append(randomId) switch message { - case let .message(text, requestedAttributes, mediaReference, replyToMessageId, localGroupingKey, _): + case let .message(text, requestedAttributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _): + for (_, file) in inlineStickers { + transaction.storeMediaIfNotPresent(media: file) + } + var peerAutoremoveTimeout: Int32? if let peer = peer as? TelegramSecretChat { var isAction = false @@ -471,6 +476,13 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, let hashtag = nsText.substring(with: entityRange) addedHashtags.append(hashtag) } + } else if case let .CustomEmoji(_, fileId) = entity.type { + let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId) + if let file = inlineStickers[mediaId] as? TelegramMediaFile { + emojiItems.append(RecentEmojiItem(.file(file))) + } else if let file = transaction.getMedia(mediaId) as? TelegramMediaFile { + emojiItems.append(RecentEmojiItem(.file(file))) + } } } break @@ -782,6 +794,19 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } var messageIds: [MessageId?] = [] if !storeMessages.isEmpty { + for emojiItem in emojiItems { + if let entry = CodableEntry(emojiItem) { + let id: RecentEmojiItemId + switch emojiItem.content { + case let .file(file): + id = RecentEmojiItemId(file.fileId) + case let .text(text): + id = RecentEmojiItemId(text) + } + transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.LocalRecentEmoji, item: OrderedItemListEntry(id: id.rawValue, contents: entry), removeTailIfCountExceeds: 20) + } + } + let globallyUniqueIdToMessageId = transaction.addMessages(storeMessages, location: .Random) for globallyUniqueId in globallyUniqueIds { messageIds.append(globallyUniqueIdToMessageId[globallyUniqueId]) diff --git a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift index 10110ca08c..24ef0cda8e 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift @@ -544,6 +544,8 @@ func inputDocumentAttributesFromFileAttributes(_ fileAttributes: [TelegramMediaF break case .NoPremium: break + case .CustomEmoji: + break } } return attributes diff --git a/submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift b/submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift index 44df047ecf..ab583b7a85 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/PendingUpdateMessageManager.swift @@ -64,7 +64,7 @@ private final class PendingUpdateMessageManagerImpl { } } - func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool) { + func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool) { if let context = self.contexts[messageId] { self.contexts.removeValue(forKey: messageId) context.disposable.dispose() @@ -75,7 +75,7 @@ private final class PendingUpdateMessageManagerImpl { self.contexts[messageId] = context let queue = self.queue - disposable.set((requestEditMessage(postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: nil) + disposable.set((requestEditMessage(postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: nil) |> deliverOn(self.queue)).start(next: { [weak self, weak context] value in queue.async { guard let strongSelf = self, let initialContext = context else { @@ -163,9 +163,9 @@ public final class PendingUpdateMessageManager { }) } - public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false) { + public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false) { self.impl.with { impl in - impl.add(messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview) + impl.add(messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview) } } diff --git a/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift index 155e3ef164..4c5098b296 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/RequestEditMessage.swift @@ -27,15 +27,15 @@ public enum RequestEditMessageError { case invalidGrouping } -func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { - return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) +func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { + return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) } -func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal { - return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false) +func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal { + return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false) |> `catch` { error -> Signal in if case .invalidReference = error { - return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true) + return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: true) } else { return .fail(error) } @@ -50,7 +50,7 @@ func requestEditMessage(postbox: Postbox, network: Network, stateManager: Accoun } } -private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal { +private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal { let uploadedMedia: Signal switch media { case .keep: @@ -95,6 +95,10 @@ private func requestEditMessageInternal(postbox: Postbox, network: Network, stat guard let message = transaction.getMessage(messageId) else { return (nil, nil, SimpleDictionary()) } + + for (_, file) in inlineStickers { + transaction.storeMediaIfNotPresent(media: file) + } if text.isEmpty { for media in message.media { diff --git a/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift b/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift index 1dce974d06..80323fdb3f 100644 --- a/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift +++ b/submodules/TelegramCore/Sources/SecretChats/SetSecretChatMessageAutoremoveTimeoutInteractively.swift @@ -16,7 +16,7 @@ func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(account: Accou transaction.setPeerChatState(peerId, state: updatedState) } - let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!))), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) + let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(timeout == nil ? 0 : timeout!))), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) } } } @@ -31,7 +31,7 @@ func _internal_addSecretChatMessageScreenshot(account: Account, peerId: PeerId) default: break } - let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) + let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))]) } } } diff --git a/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift b/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift index c4e99bdb74..0ecaca1281 100644 --- a/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift +++ b/submodules/TelegramCore/Sources/Settings/PrivacySettings.swift @@ -93,11 +93,12 @@ public struct AccountPrivacySettings: Equatable { public let forwards: SelectivePrivacySettings public let phoneNumber: SelectivePrivacySettings public let phoneDiscoveryEnabled: Bool + public let voiceMessages: SelectivePrivacySettings public let automaticallyArchiveAndMuteNonContacts: Bool public let accountRemovalTimeout: Int32 - public init(presence: SelectivePrivacySettings, groupInvitations: SelectivePrivacySettings, voiceCalls: SelectivePrivacySettings, voiceCallsP2P: SelectivePrivacySettings, profilePhoto: SelectivePrivacySettings, forwards: SelectivePrivacySettings, phoneNumber: SelectivePrivacySettings, phoneDiscoveryEnabled: Bool, automaticallyArchiveAndMuteNonContacts: Bool, accountRemovalTimeout: Int32) { + public init(presence: SelectivePrivacySettings, groupInvitations: SelectivePrivacySettings, voiceCalls: SelectivePrivacySettings, voiceCallsP2P: SelectivePrivacySettings, profilePhoto: SelectivePrivacySettings, forwards: SelectivePrivacySettings, phoneNumber: SelectivePrivacySettings, phoneDiscoveryEnabled: Bool, voiceMessages: SelectivePrivacySettings, automaticallyArchiveAndMuteNonContacts: Bool, accountRemovalTimeout: Int32) { self.presence = presence self.groupInvitations = groupInvitations self.voiceCalls = voiceCalls @@ -106,6 +107,7 @@ public struct AccountPrivacySettings: Equatable { self.forwards = forwards self.phoneNumber = phoneNumber self.phoneDiscoveryEnabled = phoneDiscoveryEnabled + self.voiceMessages = voiceMessages self.automaticallyArchiveAndMuteNonContacts = automaticallyArchiveAndMuteNonContacts self.accountRemovalTimeout = accountRemovalTimeout } @@ -135,6 +137,9 @@ public struct AccountPrivacySettings: Equatable { if lhs.phoneDiscoveryEnabled != rhs.phoneDiscoveryEnabled { return false } + if lhs.voiceMessages != rhs.voiceMessages { + return false + } if lhs.automaticallyArchiveAndMuteNonContacts != rhs.automaticallyArchiveAndMuteNonContacts { return false } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 73fa894fba..f8f3b3b666 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1379,6 +1379,8 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo let namespace: SynchronizeInstalledStickerPacksOperationNamespace if (flags & (1 << 0)) != 0 { namespace = .masks + } else if (flags & (1 << 1)) != 0 { + namespace = .emoji } else { namespace = .stickers } @@ -1554,7 +1556,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } } if !channelPeers.isEmpty { - let resetSignal = resetChannels(network: network, peers: channelPeers, state: updatedState) + let resetSignal = resetChannels(postbox: postbox, network: network, peers: channelPeers, state: updatedState) |> map { resultState -> (AccountMutableState, Bool, Int32?) in return (resultState, true, nil) } @@ -1587,7 +1589,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } } } - return resolveAssociatedMessages(network: network, state: finalState) + return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState) |> mapToSignal { resultingState -> Signal in return resolveMissingPeerChatInfos(network: network, state: resultingState) |> map { resultingState, resolveError -> AccountFinalState in @@ -1597,11 +1599,40 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } } +func extractEmojiFileIds(message: StoreMessage, fileIds: inout Set) { + for attribute in message.attributes { + if let attribute = attribute as? TextEntitiesMessageAttribute { + for entity in attribute.entities { + switch entity.type { + case let .CustomEmoji(_, fileId): + fileIds.insert(fileId) + default: + break + } + } + } + } +} -private func resolveAssociatedMessages(network: Network, state: AccountMutableState) -> Signal { +private func messagesFromOperations(state: AccountMutableState) -> [StoreMessage] { + var messages: [StoreMessage] = [] + for operation in state.operations { + switch operation { + case let .AddMessages(messagesValue, _): + messages.append(contentsOf: messagesValue) + case let .EditMessage(_, message): + messages.append(message) + default: + break + } + } + return messages +} + +private func resolveAssociatedMessages(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal { let missingMessageIds = state.referencedMessageIds.subtracting(state.storedMessages) if missingMessageIds.isEmpty { - return .single(state) + return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), result: state) } else { var missingPeers = false let _ = missingPeers @@ -1640,7 +1671,8 @@ private func resolveAssociatedMessages(network: Network, state: AccountMutableSt let fetchMessages = combineLatest(signals) - return fetchMessages |> map { results in + return fetchMessages + |> map { results in var updatedState = state for (messages, chats, users) in results { if !messages.isEmpty { @@ -1661,6 +1693,9 @@ private func resolveAssociatedMessages(network: Network, state: AccountMutableSt } return updatedState } + |> mapToSignal { updatedState -> Signal in + return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: updatedState), result: updatedState) + } } } @@ -1823,7 +1858,7 @@ func pollChannelOnce(postbox: Postbox, network: Network, peerId: PeerId, stateMa let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) return pollChannel(network: network, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in - return resolveAssociatedMessages(network: network, state: finalState) + return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState) |> mapToSignal { resultingState -> Signal in return resolveMissingPeerChatInfos(network: network, state: resultingState) |> map { resultingState, _ -> AccountFinalState in @@ -1877,7 +1912,7 @@ public func standalonePollChannelOnce(postbox: Postbox, network: Network, peerId let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) return pollChannel(network: network, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in - return resolveAssociatedMessages(network: network, state: finalState) + return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState) |> mapToSignal { resultingState -> Signal in return resolveMissingPeerChatInfos(network: network, state: resultingState) |> map { resultingState, _ -> AccountFinalState in @@ -1898,7 +1933,7 @@ func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stat |> delay(1.0, queue: .concurrentDefaultQueue()) } -private func resetChannels(network: Network, peers: [Peer], state: AccountMutableState) -> Signal { +private func resetChannels(postbox: Postbox, network: Network, peers: [Peer], state: AccountMutableState) -> Signal { var inputPeers: [Api.InputDialogPeer] = [] for peer in peers { if let inputPeer = apiInputPeer(peer) { @@ -2050,7 +2085,7 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl // TODO: delete messages later than top - return resolveAssociatedMessages(network: network, state: updatedState) + return resolveAssociatedMessages(postbox: postbox, network: network, state: updatedState) |> mapToSignal { resultingState -> Signal in return .single(resultingState) } @@ -3459,9 +3494,11 @@ func replayFinalState( }) { addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .stickers, content: .sync, noDelay: false) addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .masks, content: .sync, noDelay: false) + addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .emoji, content: .sync, noDelay: false) } else { var syncStickers = false var syncMasks = false + var syncEmoji = false loop: for operation in stickerPackOperations { switch operation { case let .add(apiSet): @@ -3498,9 +3535,11 @@ func replayFinalState( } } switch set { - case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _): + case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 3)) != 0 { namespace = Namespaces.ItemCollection.CloudMaskPacks + } else if (flags & (1 << 7)) != 0 { + namespace = Namespaces.ItemCollection.CloudEmojiPacks } else { namespace = Namespaces.ItemCollection.CloudStickerPacks } @@ -3512,6 +3551,8 @@ func replayFinalState( continue loop } else if namespace == Namespaces.ItemCollection.CloudStickerPacks && syncStickers { continue loop + } else if namespace == Namespaces.ItemCollection.CloudEmojiPacks && syncEmoji { + continue loop } var updatedInfos = transaction.getItemCollectionsInfos(namespace: info.id.namespace).map { $0.1 as! StickerPackCollectionInfo } @@ -3532,6 +3573,8 @@ func replayFinalState( collectionNamespace = Namespaces.ItemCollection.CloudStickerPacks case .masks: collectionNamespace = Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + collectionNamespace = Namespaces.ItemCollection.CloudEmojiPacks } let currentInfos = transaction.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo } if Set(currentInfos.map { $0.id.id }) != Set(ids) { @@ -3540,6 +3583,8 @@ func replayFinalState( syncStickers = true case .masks: syncMasks = true + case .emoji: + syncEmoji = true } } else { var currentDict: [ItemCollectionId: StickerPackCollectionInfo] = [:] @@ -3556,6 +3601,7 @@ func replayFinalState( case .sync: syncStickers = true syncMasks = true + syncEmoji = true break loop } } @@ -3565,6 +3611,9 @@ func replayFinalState( if syncMasks { addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .masks, content: .sync, noDelay: false) } + if syncEmoji { + addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .emoji, content: .sync, noDelay: false) + } } } diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 404bd63899..dfebb69a3d 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -316,6 +316,7 @@ public final class AccountViewTracker { private var channelPollingContexts: [PeerId: ChannelPollingContext] = [:] private var featuredStickerPacksContext: FeaturedStickerPacksContext? + private var featuredEmojiPacksContext: FeaturedStickerPacksContext? let chatHistoryPreloadManager: ChatHistoryPreloadManager @@ -1711,7 +1712,7 @@ public final class AccountViewTracker { let timestamp = CFAbsoluteTimeGetCurrent() if context.timestamp == nil || abs(context.timestamp! - timestamp) > 60.0 * 60.0 { context.timestamp = timestamp - context.disposable.set(updatedFeaturedStickerPacks(network: account.network, postbox: account.postbox).start()) + context.disposable.set(updatedFeaturedStickerPacks(network: account.network, postbox: account.postbox, category: .stickerPacks).start()) } let index = context.subscribers.add(Void()) @@ -1736,6 +1737,56 @@ public final class AccountViewTracker { } } + public func featuredEmojiPacks() -> Signal<[FeaturedStickerPackItem], NoError> { + return Signal { subscriber in + if let account = self.account { + let view = account.postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)]).start(next: { next in + if let view = next.views[.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks)] as? OrderedItemListView { + subscriber.putNext(view.items.map { $0.contents.get(FeaturedStickerPackItem.self)! }) + } else { + subscriber.putNext([]) + } + }, completed: { + subscriber.putCompletion() + }) + let disposable = MetaDisposable() + self.queue.async { + let context: FeaturedStickerPacksContext + if let current = self.featuredEmojiPacksContext { + context = current + } else { + context = FeaturedStickerPacksContext() + self.featuredEmojiPacksContext = context + } + + let timestamp = CFAbsoluteTimeGetCurrent() + if context.timestamp == nil || abs(context.timestamp! - timestamp) > 60.0 * 60.0 { + context.timestamp = timestamp + context.disposable.set(updatedFeaturedStickerPacks(network: account.network, postbox: account.postbox, category: .emojiPacks).start()) + } + + let index = context.subscribers.add(Void()) + + disposable.set(ActionDisposable { + self.queue.async { + if let context = self.featuredEmojiPacksContext { + context.subscribers.remove(index) + } + } + }) + } + return ActionDisposable { + view.dispose() + disposable.dispose() + } + } else { + subscriber.putNext([]) + subscriber.putCompletion() + return EmptyDisposable + } + } + } + public func callListView(type: CallListViewType, index: MessageIndex, count: Int) -> Signal { if let account = self.account { let granularity: Int32 = 60 * 60 * 24 diff --git a/submodules/TelegramCore/Sources/State/FetchChatList.swift b/submodules/TelegramCore/Sources/State/FetchChatList.swift index bcf6be922b..bc0d24b245 100644 --- a/submodules/TelegramCore/Sources/State/FetchChatList.swift +++ b/submodules/TelegramCore/Sources/State/FetchChatList.swift @@ -295,7 +295,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo } return combineLatest(folderSignals) - |> map { folders -> FetchedChatList? in + |> mapToSignal { folders -> Signal in var peers: [Peer] = [] var peerPresences: [PeerId: PeerPresence] = [:] var notificationSettings: [PeerId: PeerNotificationSettings] = [:] @@ -372,7 +372,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo } } - return FetchedChatList( + let result: FetchedChatList? = FetchedChatList( chatPeerIds: parsedRemoteChats.itemIds + (pinnedItemIds ?? []), peers: peers, peerPresences: peerPresences, @@ -390,6 +390,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo folderSummaries: folderSummaries, peerGroupIds: peerGroupIds ) + return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: storeMessages, result: result) } } } diff --git a/submodules/TelegramCore/Sources/State/Holes.swift b/submodules/TelegramCore/Sources/State/Holes.swift index 8ca1cbe565..04ca364162 100644 --- a/submodules/TelegramCore/Sources/State/Holes.swift +++ b/submodules/TelegramCore/Sources/State/Holes.swift @@ -43,7 +43,58 @@ enum FetchMessageHistoryHoleSource { } } -func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal { +func resolveUnknownEmojiFiles(postbox: Postbox, source: FetchMessageHistoryHoleSource, messages: [StoreMessage], result: T) -> Signal { + var fileIds = Set() + + for message in messages { + extractEmojiFileIds(message: message, fileIds: &fileIds) + } + + if fileIds.isEmpty { + return .single(result) + } else { + return postbox.transaction { transaction -> Set in + return transaction.filterStoredMediaIds(namespace: Namespaces.Media.CloudFile, ids: fileIds) + } + |> mapToSignal { unknownIds -> Signal in + if unknownIds.isEmpty { + return .single(result) + } else { + var signals: [Signal<[Api.Document]?, NoError>] = [] + var remainingIds = Array(unknownIds) + while !remainingIds.isEmpty { + let partIdCount = min(100, remainingIds.count) + let partIds = remainingIds.prefix(partIdCount) + remainingIds.removeFirst(partIdCount) + signals.append(source.request(Api.functions.messages.getCustomEmojiDocuments(documentId: Array(partIds))) + |> map(Optional.init) + |> `catch` { _ -> Signal<[Api.Document]?, NoError> in + return .single(nil) + }) + } + + return combineLatest(signals) + |> mapToSignal { documentSets -> Signal in + return postbox.transaction { transaction -> T in + for documentSet in documentSets { + if let documentSet = documentSet { + for document in documentSet { + if let file = telegramMediaFileFromApiDocument(document) { + transaction.storeMediaIfNotPresent(media: file) + } + } + } + } + + return result + } + } + } + } + } +} + +private func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal { return postbox.transaction { transaction -> Signal in var storedIds = Set() var referencedIds = Set() @@ -60,7 +111,12 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHis referencedIds.subtract(transaction.filterStoredMessageIds(referencedIds)) if referencedIds.isEmpty { - return .single(f(transaction, [], [])) + return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, result: Void()) + |> mapToSignal { _ -> Signal in + return postbox.transaction { transaction -> T in + return f(transaction, [], []) + } + } } else { var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = [] for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedIds) { @@ -117,8 +173,12 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHis additionalPeers.append(TelegramUser(user: user)) } } - return postbox.transaction { transaction -> T in - return f(transaction, additionalPeers, additionalMessages) + + return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, result: Void()) + |> mapToSignal { _ -> Signal in + return postbox.transaction { transaction -> T in + return f(transaction, additionalPeers, additionalMessages) + } } } } @@ -528,7 +588,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH } } - return withResolvedAssociatedMessages(postbox: postbox, source: source, peers: Dictionary(peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: storeMessages, { transaction, additionalPeers, additionalMessages -> FetchMessageHistoryHoleResult in + return withResolvedAssociatedMessages(postbox: postbox, source: source, peers: Dictionary(peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: storeMessages, { transaction, additionalPeers, additionalMessages -> FetchMessageHistoryHoleResult? in let _ = transaction.addMessages(storeMessages, location: .Random) let _ = transaction.addMessages(additionalMessages, location: .Random) var filledRange: ClosedRange @@ -623,13 +683,14 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH print("fetchMessageHistoryHole for \(peerInput) space \(space) done") - return FetchMessageHistoryHoleResult( + let result = FetchMessageHistoryHoleResult( removedIndices: IndexSet(integersIn: Int(filledRange.lowerBound) ... Int(filledRange.upperBound)), strictRemovedIndices: strictFilledIndices, actualPeerId: storeMessages.first?.id.peerId, actualThreadId: storeMessages.first?.threadId, ids: fullIds ) + return result }) } } @@ -665,7 +726,7 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId } |> ignoreValues } - return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages in + return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in updatePeers(transaction: transaction, peers: fetchedChats.peers + additionalPeers, update: { _, updated -> Peer in return updated }) @@ -716,8 +777,6 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId for (groupId, summary) in fetchedChats.folderSummaries { transaction.resetPeerGroupSummary(groupId: groupId, namespace: Namespaces.Message.Cloud, summary: summary) } - - return }) |> ignoreValues } diff --git a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift index 8cd7216db5..eed20d05ef 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift @@ -544,6 +544,8 @@ private func decryptedAttributes46(_ attributes: [TelegramMediaFileAttribute], t break case .NoPremium: break + case .CustomEmoji: + break } } return result @@ -605,6 +607,8 @@ private func decryptedAttributes73(_ attributes: [TelegramMediaFileAttribute], t break case .NoPremium: break + case .CustomEmoji: + break } } return result @@ -666,6 +670,8 @@ private func decryptedAttributes101(_ attributes: [TelegramMediaFileAttribute], break case .NoPremium: break + case .CustomEmoji: + break } } return result @@ -715,7 +721,7 @@ private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi break case .Spoiler: break - case .AnimatedEmoji: + case .CustomEmoji: break case .Custom: break @@ -768,7 +774,7 @@ private func decryptedEntities101(_ entities: [MessageTextEntity]?) -> [SecretAp break case .Spoiler: break - case .AnimatedEmoji: + case .CustomEmoji: break case .Custom: break diff --git a/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift index 1b73b655f3..30ebc429d2 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift @@ -72,6 +72,8 @@ func managedSynchronizeInstalledStickerPacksOperations(postbox: Postbox, network tag = OperationLogTags.SynchronizeInstalledStickerPacks case .masks: tag = OperationLogTags.SynchronizeInstalledMasks + case .emoji: + tag = OperationLogTags.SynchronizeInstalledEmoji } let helper = Atomic(value: ManagedSynchronizeInstalledStickerPacksOperationsHelper()) @@ -126,7 +128,7 @@ private func hashForStickerPackInfos(_ infos: [StickerPackCollectionInfo]) -> In var acc: UInt64 = 0 for info in infos { - combineInt64Hash(&acc, with: UInt64(UInt32(bitPattern: info.hash))) + combineInt64Hash(&acc, with: UInt64(bitPattern: Int64(info.hash))) } return finalizeInt64Hash(acc) @@ -218,10 +220,12 @@ private func installRemoteStickerPacks(network: Network, infos: [StickerPackColl var archivedIds = Set() for archivedSet in archivedSets { switch archivedSet { - case let .stickerSetCovered(set, _): - archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id) - case let .stickerSetMultiCovered(set, _): - archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id) + case let .stickerSetCovered(set, _): + archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id) + case let .stickerSetMultiCovered(set, _): + archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id) + case let .stickerSetFullCovered(set, _, _): + archivedIds.insert(StickerPackCollectionInfo(apiSet: set, namespace: info.id.namespace).id) } } return archivedIds @@ -295,6 +299,8 @@ private func reorderRemoteStickerPacks(network: Network, namespace: SynchronizeI break case .masks: flags |= (1 << 0) + case .emoji: + flags |= (1 << 1) } return network.request(Api.functions.messages.reorderStickerSets(flags: flags, order: ids.map { $0.id })) |> `catch` { _ -> Signal in @@ -312,6 +318,8 @@ private func synchronizeInstalledStickerPacks(transaction: Transaction, postbox: collectionNamespace = Namespaces.ItemCollection.CloudStickerPacks case .masks: collectionNamespace = Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + collectionNamespace = Namespaces.ItemCollection.CloudEmojiPacks } let localCollectionInfos = transaction.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo } @@ -435,6 +443,8 @@ private func continueSynchronizeInstalledStickerPacks(transaction: Transaction, collectionNamespace = Namespaces.ItemCollection.CloudStickerPacks case .masks: collectionNamespace = Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + collectionNamespace = Namespaces.ItemCollection.CloudEmojiPacks } let localCollectionInfos = transaction.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo } @@ -446,6 +456,8 @@ private func continueSynchronizeInstalledStickerPacks(transaction: Transaction, request = network.request(Api.functions.messages.getAllStickers(hash: initialLocalHash)) case .masks: request = network.request(Api.functions.messages.getMaskStickers(hash: initialLocalHash)) + case .emoji: + request = network.request(Api.functions.messages.getEmojiStickers(hash: initialLocalHash)) } let sequence = request diff --git a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift index 620c47927a..e51aaeb91c 100644 --- a/submodules/TelegramCore/Sources/State/PendingMessageManager.swift +++ b/submodules/TelegramCore/Sources/State/PendingMessageManager.swift @@ -56,6 +56,7 @@ public enum PendingMessageFailureReason { case mediaRestricted case slowmodeActive case tooMuchScheduled + case voiceMessagesForbidden } private func reasonForError(_ error: String) -> PendingMessageFailureReason? { @@ -69,6 +70,8 @@ private func reasonForError(_ error: String) -> PendingMessageFailureReason? { return .slowmodeActive } else if error.hasPrefix("SCHEDULE_TOO_MUCH") { return .tooMuchScheduled + } else if error.hasPrefix("VOICE_MESSAGES_FORBIDDEN") { + return .voiceMessagesForbidden } else { return nil } diff --git a/submodules/TelegramCore/Sources/State/Serialization.swift b/submodules/TelegramCore/Sources/State/Serialization.swift index f0ea775946..dc83c6cd28 100644 --- a/submodules/TelegramCore/Sources/State/Serialization.swift +++ b/submodules/TelegramCore/Sources/State/Serialization.swift @@ -210,7 +210,7 @@ public class BoxedMessage: NSObject { public class Serialization: NSObject, MTSerialization { public func currentLayer() -> UInt { - return 143 + return 144 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/submodules/TelegramCore/Sources/State/StickerManagement.swift b/submodules/TelegramCore/Sources/State/StickerManagement.swift index 3b17917a19..68ab5b358a 100644 --- a/submodules/TelegramCore/Sources/State/StickerManagement.swift +++ b/submodules/TelegramCore/Sources/State/StickerManagement.swift @@ -3,6 +3,30 @@ import TelegramApi import Postbox import SwiftSignalKit +enum FeaturedStickerPacksCategory { + case stickerPacks + case emojiPacks +} + +extension FeaturedStickerPacksCategory { + var itemListNamespace: Int32 { + switch self { + case .stickerPacks: + return Namespaces.OrderedItemList.CloudFeaturedStickerPacks + case .emojiPacks: + return Namespaces.OrderedItemList.CloudFeaturedEmojiPacks + } + } + + var collectionIdNamespace: Int32 { + switch self { + case .stickerPacks: + return Namespaces.ItemCollection.CloudStickerPacks + case .emojiPacks: + return Namespaces.ItemCollection.CloudEmojiPacks + } + } +} private func hashForIdsReverse(_ ids: [Int64]) -> Int64 { var acc: UInt64 = 0 @@ -17,15 +41,16 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal Void in addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .stickers, content: .sync, noDelay: false) addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .masks, content: .sync, noDelay: false) + addSynchronizeInstalledStickerPacksOperation(transaction: transaction, namespace: .emoji, content: .sync, noDelay: false) addSynchronizeSavedGifsOperation(transaction: transaction, operation: .sync) addSynchronizeSavedStickersOperation(transaction: transaction, operation: .sync) addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .sync) } |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart } -func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal { +func updatedFeaturedStickerPacks(network: Network, postbox: Postbox, category: FeaturedStickerPacksCategory) -> Signal { return postbox.transaction { transaction -> Signal in - let initialPacks = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) + let initialPacks = transaction.getOrderedListItems(collectionId: category.itemListNamespace) var initialPackMap: [Int64: FeaturedStickerPackItem] = [:] for entry in initialPacks { let item = entry.contents.get(FeaturedStickerPackItem.self)! @@ -36,18 +61,29 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal retryRequest - |> mapToSignal { result -> Signal in - return postbox.transaction { transaction -> Void in + + struct FeaturedListContent { + var unreadIds: Set + var packs: [FeaturedStickerPackItem] + var isPremium: Bool + } + enum FeaturedList { + case notModified + case content(FeaturedListContent) + } + let signal: Signal + switch category { + case .stickerPacks: + signal = network.request(Api.functions.messages.getFeaturedStickers(hash: initialHash)) + |> map { result -> FeaturedList in switch result { case .featuredStickersNotModified: - break + return .notModified case let .featuredStickers(flags, _, _, sets, unread): let unreadIds = Set(unread) var updatedPacks: [FeaturedStickerPackItem] = [] for set in sets { - var (info, items) = parsePreviewStickerSet(set) + var (info, items) = parsePreviewStickerSet(set, namespace: category.collectionIdNamespace) if let previousPack = initialPackMap[info.id.id] { if previousPack.info.hash == info.hash { items = previousPack.topItems @@ -55,7 +91,56 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal OrderedItemListEntry? in + let isPremium = flags & (1 << 0) != 0 + return .content(FeaturedListContent( + unreadIds: unreadIds, + packs: updatedPacks, + isPremium: isPremium + )) + } + } + |> `catch` { _ -> Signal in + return .single(.notModified) + } + case .emojiPacks: + signal = network.request(Api.functions.messages.getFeaturedEmojiStickers(hash: initialHash)) + |> map { result -> FeaturedList in + switch result { + case .featuredStickersNotModified: + return .notModified + case let .featuredStickers(flags, _, _, sets, unread): + let unreadIds = Set(unread) + var updatedPacks: [FeaturedStickerPackItem] = [] + for set in sets { + var (info, items) = parsePreviewStickerSet(set, namespace: category.collectionIdNamespace) + if let previousPack = initialPackMap[info.id.id] { + if previousPack.info.hash == info.hash { + items = previousPack.topItems + } + } + updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id))) + } + let isPremium = flags & (1 << 0) != 0 + return .content(FeaturedListContent( + unreadIds: unreadIds, + packs: updatedPacks, + isPremium: isPremium + )) + } + } + |> `catch` { _ -> Signal in + return .single(.notModified) + } + } + + return signal + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction -> Void in + switch result { + case .notModified: + break + case let .content(content): + transaction.replaceOrderedItemListItems(collectionId: category.itemListNamespace, items: content.packs.compactMap { item -> OrderedItemListEntry? in if let entry = CodableEntry(item) { return OrderedItemListEntry(id: FeaturedStickerPackItemId(item.info.id.id).rawValue, contents: entry) } else { @@ -63,14 +148,14 @@ func updatedFeaturedStickerPacks(network: Network, postbox: Postbox) -> Signal switchToLatest + } + |> switchToLatest } public func requestOldFeaturedStickerPacks(network: Network, postbox: Postbox, offset: Int, limit: Int) -> Signal<[FeaturedStickerPackItem], NoError> { @@ -84,7 +169,7 @@ public func requestOldFeaturedStickerPacks(network: Network, postbox: Postbox, o let unreadIds = Set(unread) var updatedPacks: [FeaturedStickerPackItem] = [] for set in sets { - let (info, items) = parsePreviewStickerSet(set) + let (info, items) = parsePreviewStickerSet(set, namespace: Namespaces.ItemCollection.CloudStickerPacks) updatedPacks.append(FeaturedStickerPackItem(info: info, topItems: items, unread: unreadIds.contains(info.id.id))) } return updatedPacks @@ -124,23 +209,55 @@ public func preloadedFeaturedStickerSet(network: Network, postbox: Postbox, id: } |> switchToLatest } -func parsePreviewStickerSet(_ set: Api.StickerSetCovered, namespace: ItemCollectionId.Namespace = Namespaces.ItemCollection.CloudStickerPacks) -> (StickerPackCollectionInfo, [StickerPackItem]) { +func parsePreviewStickerSet(_ set: Api.StickerSetCovered, namespace: ItemCollectionId.Namespace) -> (StickerPackCollectionInfo, [StickerPackItem]) { switch set { - case let .stickerSetCovered(set, cover): - let info = StickerPackCollectionInfo(apiSet: set, namespace: namespace) - var items: [StickerPackItem] = [] + case let .stickerSetCovered(set, cover): + let info = StickerPackCollectionInfo(apiSet: set, namespace: namespace) + var items: [StickerPackItem] = [] + if let file = telegramMediaFileFromApiDocument(cover), let id = file.id { + items.append(StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: id.id), file: file, indexKeys: [])) + } + return (info, items) + case let .stickerSetMultiCovered(set, covers): + let info = StickerPackCollectionInfo(apiSet: set, namespace: namespace) + var items: [StickerPackItem] = [] + for cover in covers { if let file = telegramMediaFileFromApiDocument(cover), let id = file.id { items.append(StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: id.id), file: file, indexKeys: [])) } - return (info, items) - case let .stickerSetMultiCovered(set, covers): - let info = StickerPackCollectionInfo(apiSet: set, namespace: namespace) - var items: [StickerPackItem] = [] - for cover in covers { - if let file = telegramMediaFileFromApiDocument(cover), let id = file.id { - items.append(StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: id.id), file: file, indexKeys: [])) + } + return (info, items) + case let .stickerSetFullCovered(set, packs, documents): + var indexKeysByFile: [MediaId: [MemoryBuffer]] = [:] + for pack in packs { + switch pack { + case let .stickerPack(text, fileIds): + let key = ValueBoxKey(text).toMemoryBuffer() + for fileId in fileIds { + let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId) + if indexKeysByFile[mediaId] == nil { + indexKeysByFile[mediaId] = [key] + } else { + indexKeysByFile[mediaId]!.append(key) + } } + break } - return (info, items) + } + + let info = StickerPackCollectionInfo(apiSet: set, namespace: namespace) + var items: [StickerPackItem] = [] + for document in documents { + if let file = telegramMediaFileFromApiDocument(document), let id = file.id { + let fileIndexKeys: [MemoryBuffer] + if let indexKeys = indexKeysByFile[id] { + fileIndexKeys = indexKeys + } else { + fileIndexKeys = [] + } + items.append(StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: id.id), file: file, indexKeys: fileIndexKeys)) + } + } + return (info, items) } } diff --git a/submodules/TelegramCore/Sources/State/SynchronizeInstalledStickerPacksOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeInstalledStickerPacksOperation.swift index 30939ae228..72656ed868 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeInstalledStickerPacksOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeInstalledStickerPacksOperation.swift @@ -14,6 +14,8 @@ public func addSynchronizeInstalledStickerPacksOperation(transaction: Transactio operationNamespace = .stickers case Namespaces.ItemCollection.CloudMaskPacks: operationNamespace = .masks + case Namespaces.ItemCollection.CloudEmojiPacks: + operationNamespace = .emoji default: return } @@ -31,6 +33,9 @@ func addSynchronizeInstalledStickerPacksOperation(transaction: Transaction, name case .masks: tag = OperationLogTags.SynchronizeInstalledMasks itemCollectionNamespace = Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + tag = OperationLogTags.SynchronizeInstalledEmoji + itemCollectionNamespace = Namespaces.ItemCollection.CloudEmojiPacks } var previousStickerPackIds: [ItemCollectionId]? var archivedPacks: [ItemCollectionId] = [] diff --git a/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift b/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift index 4078d75f68..714ebe6242 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeRecentlyUsedMediaOperations.swift @@ -45,3 +45,6 @@ func _internal_clearRecentlyUsedStickers(transaction: Transaction) { addSynchronizeRecentlyUsedMediaOperation(transaction: transaction, category: .stickers, operation: .clear) } +func _internal_clearRecentlyUsedEmoji(transaction: Transaction) { + transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.LocalRecentEmoji, items: []) +} diff --git a/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift b/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift index d237ff6013..7f633325d0 100644 --- a/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift +++ b/submodules/TelegramCore/Sources/State/SynchronizeSavedStickersOperation.swift @@ -61,7 +61,7 @@ public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMe if !found { fetchReference = packReference } - case .animatedEmoji, .animatedEmojiAnimations, .dice: + case .animatedEmoji, .animatedEmojiAnimations, .dice, .premiumGifts: break } if let fetchReference = fetchReference { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift index cb16fd9f6e..b5f8795130 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift @@ -93,6 +93,6 @@ public final class BotInfo: PostboxCoding, Equatable { } public static func ==(lhs: BotInfo, rhs: BotInfo) -> Bool { - return lhs.description == rhs.description && lhs.commands == rhs.commands && lhs.menuButton == rhs.menuButton && lhs.photo != rhs.photo + return lhs.description == rhs.description && lhs.commands == rhs.commands && lhs.menuButton == rhs.menuButton && lhs.photo == rhs.photo } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index 4813cb00b1..fb0366c200 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -49,6 +49,42 @@ public enum CachedPeerAutoremoveTimeout: Equatable, PostboxCoding { } } +public struct CachedPremiumGiftOption: Equatable, PostboxCoding { + public let months: Int32 + public let currency: String + public let amount: Int64 + public let botUrl: String + public let storeProductId: String? + + public init(months: Int32, currency: String, amount: Int64, botUrl: String, storeProductId: String?) { + self.months = months + self.currency = currency + self.amount = amount + self.botUrl = botUrl + self.storeProductId = storeProductId + } + + public init(decoder: PostboxDecoder) { + self.months = decoder.decodeInt32ForKey("months", orElse: 0) + self.currency = decoder.decodeStringForKey("currency", orElse: "") + self.amount = decoder.decodeInt64ForKey("amount", orElse: 0) + self.botUrl = decoder.decodeStringForKey("botUrl", orElse: "") + self.storeProductId = decoder.decodeOptionalStringForKey("storeProductId") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.months, forKey: "months") + encoder.encodeString(self.currency, forKey: "currency") + encoder.encodeInt64(self.amount, forKey: "amount") + encoder.encodeString(self.botUrl, forKey: "botUrl") + if let storeProductId = self.storeProductId { + encoder.encodeString(storeProductId, forKey: "storeProductId") + } else { + encoder.encodeNil(forKey: "storeProductId") + } + } +} + public final class CachedUserData: CachedPeerData { public let about: String? public let botInfo: BotInfo? @@ -64,6 +100,8 @@ public final class CachedUserData: CachedPeerData { public let autoremoveTimeout: CachedPeerAutoremoveTimeout public let themeEmoticon: String? public let photo: TelegramMediaImage? + public let premiumGiftOptions: [CachedPremiumGiftOption] + public let voiceMessagesAvailable: Bool public let peerIds: Set public let messageIds: Set @@ -84,11 +122,13 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = .unknown self.themeEmoticon = nil self.photo = nil + self.premiumGiftOptions = [] + self.voiceMessagesAvailable = true self.peerIds = Set() self.messageIds = Set() } - public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: TelegramMediaImage?) { + public init(about: String?, botInfo: BotInfo?, peerStatusSettings: PeerStatusSettings?, pinnedMessageId: MessageId?, isBlocked: Bool, commonGroupCount: Int32, voiceCallsAvailable: Bool, videoCallsAvailable: Bool, callsPrivate: Bool, canPinMessages: Bool, hasScheduledMessages: Bool, autoremoveTimeout: CachedPeerAutoremoveTimeout, themeEmoticon: String?, photo: TelegramMediaImage?, premiumGiftOptions: [CachedPremiumGiftOption], voiceMessagesAvailable: Bool) { self.about = about self.botInfo = botInfo self.peerStatusSettings = peerStatusSettings @@ -103,6 +143,8 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = autoremoveTimeout self.themeEmoticon = themeEmoticon self.photo = photo + self.premiumGiftOptions = premiumGiftOptions + self.voiceMessagesAvailable = voiceMessagesAvailable self.peerIds = Set() @@ -143,6 +185,9 @@ public final class CachedUserData: CachedPeerData { } else { self.photo = nil } + + self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption] + self.voiceMessagesAvailable = decoder.decodeInt32ForKey("vma", orElse: 0) != 0 self.peerIds = Set() @@ -197,6 +242,9 @@ public final class CachedUserData: CachedPeerData { } else { encoder.encodeNil(forKey: "ph") } + + encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo") + encoder.encodeInt32(self.voiceMessagesAvailable ? 1 : 0, forKey: "vma") } public func isEqual(to: CachedPeerData) -> Bool { @@ -211,62 +259,70 @@ public final class CachedUserData: CachedPeerData { return false } - return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.themeEmoticon == other.themeEmoticon && self.photo == other.photo + return other.about == self.about && other.botInfo == self.botInfo && self.peerStatusSettings == other.peerStatusSettings && self.isBlocked == other.isBlocked && self.commonGroupCount == other.commonGroupCount && self.voiceCallsAvailable == other.voiceCallsAvailable && self.videoCallsAvailable == other.videoCallsAvailable && self.callsPrivate == other.callsPrivate && self.hasScheduledMessages == other.hasScheduledMessages && self.autoremoveTimeout == other.autoremoveTimeout && self.themeEmoticon == other.themeEmoticon && self.photo == other.photo && self.premiumGiftOptions == other.premiumGiftOptions && self.voiceMessagesAvailable == other.voiceMessagesAvailable } public func withUpdatedAbout(_ about: String?) -> CachedUserData { - return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedBotInfo(_ botInfo: BotInfo?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedPeerStatusSettings(_ peerStatusSettings: PeerStatusSettings) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedIsBlocked(_ isBlocked: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedCommonGroupCount(_ commonGroupCount: Int32) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedVoiceCallsAvailable(_ voiceCallsAvailable: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedVideoCallsAvailable(_ videoCallsAvailable: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedCallsPrivate(_ callsPrivate: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedCanPinMessages(_ canPinMessages: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedHasScheduledMessages(_ hasScheduledMessages: Bool) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedAutoremoveTimeout(_ autoremoveTimeout: CachedPeerAutoremoveTimeout) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedThemeEmoticon(_ themeEmoticon: String?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: themeEmoticon, photo: self.photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) } public func withUpdatedPhoto(_ photo: TelegramMediaImage?) -> CachedUserData { - return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: photo) + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) + } + + public func withUpdatedPremiumGiftOptions(_ premiumGiftOptions: [CachedPremiumGiftOption]) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: premiumGiftOptions, voiceMessagesAvailable: self.voiceMessagesAvailable) + } + + public func withUpdatedVoiceMessagesAvailable(_ voiceMessagesAvailable: Bool) -> CachedUserData { + return CachedUserData(about: self.about, botInfo: self.botInfo, peerStatusSettings: self.peerStatusSettings, pinnedMessageId: self.pinnedMessageId, isBlocked: self.isBlocked, commonGroupCount: self.commonGroupCount, voiceCallsAvailable: self.voiceCallsAvailable, videoCallsAvailable: self.videoCallsAvailable, callsPrivate: self.callsPrivate, canPinMessages: self.canPinMessages, hasScheduledMessages: self.hasScheduledMessages, autoremoveTimeout: self.autoremoveTimeout, themeEmoticon: self.themeEmoticon, photo: self.photo, premiumGiftOptions: self.premiumGiftOptions, voiceMessagesAvailable: voiceMessagesAvailable) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_MediaReference.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_MediaReference.swift index 2516478eec..a1b029630c 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_MediaReference.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_MediaReference.swift @@ -225,6 +225,7 @@ public enum AnyMediaReference: Equatable { case savedGif(media: Media) case avatarList(peer: PeerReference, media: Media) case attachBot(peer: PeerReference, media: Media) + case customEmoji(media: Media) public static func ==(lhs: AnyMediaReference, rhs: AnyMediaReference) -> Bool { switch lhs { @@ -270,6 +271,12 @@ public enum AnyMediaReference: Equatable { } else { return false } + case let .customEmoji(lhsMedia): + if case let .customEmoji(rhsMedia) = rhs, lhsMedia.isEqual(to: rhsMedia) { + return true + } else { + return false + } } } @@ -289,6 +296,8 @@ public enum AnyMediaReference: Equatable { return nil case .attachBot: return nil + case .customEmoji: + return nil } } @@ -322,6 +331,10 @@ public enum AnyMediaReference: Equatable { if let media = media as? T { return .attachBot(peer: peer, media: media) } + case let .customEmoji(media): + if let media = media as? T { + return .customEmoji(media: media) + } } return nil } @@ -342,6 +355,8 @@ public enum AnyMediaReference: Equatable { return media case let .attachBot(_, media): return media + case let .customEmoji(media): + return media } } @@ -421,6 +436,7 @@ public enum MediaReference { case savedGif case avatarList case attachBot + case customEmoji } case standalone(media: T) @@ -430,6 +446,7 @@ public enum MediaReference { case savedGif(media: T) case avatarList(peer: PeerReference, media: T) case attachBot(peer: PeerReference, media: T) + case customEmoji(media: T) public init?(decoder: PostboxDecoder) { guard let caseIdValue = decoder.decodeOptionalInt32ForKey("_r"), let caseId = CodingCase(rawValue: caseIdValue) else { @@ -476,6 +493,11 @@ public enum MediaReference { return nil } self = .attachBot(peer: peer, media: media) + case .customEmoji: + guard let media = decoder.decodeObjectForKey("m") as? T else { + return nil + } + self = .customEmoji(media: media) } } @@ -507,6 +529,9 @@ public enum MediaReference { encoder.encodeInt32(CodingCase.attachBot.rawValue, forKey: "_r") encoder.encodeObject(peer, forKey: "pr") encoder.encodeObject(media, forKey: "m") + case let .customEmoji(media): + encoder.encodeInt32(CodingCase.customEmoji.rawValue, forKey: "_r") + encoder.encodeObject(media, forKey: "m") } } @@ -526,6 +551,8 @@ public enum MediaReference { return .avatarList(peer: peer, media: media) case let .attachBot(peer, media): return .attachBot(peer: peer, media: media) + case let .customEmoji(media): + return .customEmoji(media: media) } } @@ -549,6 +576,8 @@ public enum MediaReference { return media case let .attachBot(_, media): return media + case let .customEmoji(media): + return media } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index acd5448e77..0b86fecc06 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -46,6 +46,8 @@ public struct Namespaces { public static let CloudDice: Int32 = 4 public static let CloudAnimatedEmojiAnimations: Int32 = 5 public static let CloudAnimatedEmojiReactions: Int32 = 6 + public static let CloudPremiumGifts: Int32 = 7 + public static let CloudEmojiPacks: Int32 = 8 } public struct OrderedItemList { @@ -63,6 +65,8 @@ public struct Namespaces { public static let RecentDownloads: Int32 = 11 public static let PremiumStickers: Int32 = 12 public static let CloudPremiumStickers: Int32 = 13 + public static let LocalRecentEmoji: Int32 = 14 + public static let CloudFeaturedEmojiPacks: Int32 = 15 } public struct CachedItemCollection { @@ -164,6 +168,7 @@ public struct OperationLogTags { public static let SynchronizeEmojiKeywords = PeerOperationLogTag(value: 19) public static let SynchronizeChatListFilters = PeerOperationLogTag(value: 20) public static let SynchronizeMarkAllUnseenReactions = PeerOperationLogTag(value: 21) + public static let SynchronizeInstalledEmoji = PeerOperationLogTag(value: 22) } public struct LegacyPeerSummaryCounterTags: OptionSet, Sequence, Hashable { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift index 74999632b9..c62293053d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift @@ -49,3 +49,106 @@ public final class RecentMediaItem: Codable, Equatable { return lhs.media.isEqual(to: rhs.media) } } + +public struct RecentEmojiItemId { + public enum Id { + case media(MediaId) + case text(String) + } + + public let rawValue: MemoryBuffer + public let id: Id + + public init(_ rawValue: MemoryBuffer) { + self.rawValue = rawValue + + assert(rawValue.length >= 1) + var type: UInt8 = 0 + memcpy(&type, rawValue.memory.advanced(by: 0), 1) + + if type == 0 { + assert(rawValue.length == 1 + 4 + 8) + var mediaIdNamespace: Int32 = 0 + var mediaIdId: Int64 = 0 + memcpy(&mediaIdNamespace, rawValue.memory.advanced(by: 1), 4) + memcpy(&mediaIdId, rawValue.memory.advanced(by: 1 + 4), 8) + self.id = .media(MediaId(namespace: mediaIdNamespace, id: mediaIdId)) + } else if type == 1 { + var length: UInt16 = 0 + assert(rawValue.length >= 1 + 2) + memcpy(&length, rawValue.memory.advanced(by: 1), 2) + + assert(rawValue.length >= 1 + 2 + Int(length)) + + self.id = .text(String(data: Data(bytes: rawValue.memory.advanced(by: 1 + 2), count: Int(length)), encoding: .utf8) ?? ".") + } else { + assert(false) + self.id = .text(".") + } + } + + public init(_ mediaId: MediaId) { + self.id = .media(mediaId) + + var mediaIdNamespace: Int32 = mediaId.namespace + var mediaIdId: Int64 = mediaId.id + self.rawValue = MemoryBuffer(memory: malloc(1 + 4 + 8)!, capacity: 1 + 4 + 8, length: 1 + 4 + 8, freeWhenDone: true) + var type: UInt8 = 0 + memcpy(self.rawValue.memory.advanced(by: 0), &type, 1) + memcpy(self.rawValue.memory.advanced(by: 1), &mediaIdNamespace, 4) + memcpy(self.rawValue.memory.advanced(by: 1 + 4), &mediaIdId, 8) + } + + public init(_ text: String) { + self.id = .text(text) + + let data = text.data(using: .utf8) ?? Data() + var length: UInt16 = UInt16(data.count) + + self.rawValue = MemoryBuffer(memory: malloc(1 + 2 + data.count)!, capacity: 1 + 2 + data.count, length: 1 + 2 + data.count, freeWhenDone: true) + var type: UInt8 = 1 + memcpy(self.rawValue.memory.advanced(by: 0), &type, 1) + memcpy(self.rawValue.memory.advanced(by: 1), &length, 2) + data.withUnsafeBytes { bytes in + let _ = memcpy(self.rawValue.memory.advanced(by: 1 + 2), bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), bytes.count) + } + } +} + +public final class RecentEmojiItem: Codable, Equatable { + public enum Content: Equatable { + case file(TelegramMediaFile) + case text(String) + } + + public let content: Content + + public init(_ content: Content) { + self.content = content + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: StringCodingKey.self) + + if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") { + self.content = .file(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data)))) + } else { + self.content = .text(try container.decode(String.self, forKey: "s")) + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: StringCodingKey.self) + + switch self.content { + case let .file(file): + try container.encode(PostboxEncoder().encodeObjectToRawData(file), forKey: "m") + case let .text(string): + try container.encode(string, forKey: "s") + } + } + + public static func ==(lhs: RecentEmojiItem, rhs: RecentEmojiItem) -> Bool { + return lhs.content == rhs.content + } +} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift index 599ebc1f36..bf6c9ad840 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift @@ -27,6 +27,9 @@ public struct StickerPackCollectionInfoFlags: OptionSet { if flags.contains(StickerPackCollectionInfoFlags.isVideo) { rawValue |= StickerPackCollectionInfoFlags.isVideo.rawValue } + if flags.contains(StickerPackCollectionInfoFlags.isEmoji) { + rawValue |= StickerPackCollectionInfoFlags.isEmoji.rawValue + } self.rawValue = rawValue } @@ -35,6 +38,7 @@ public struct StickerPackCollectionInfoFlags: OptionSet { public static let isOfficial = StickerPackCollectionInfoFlags(rawValue: 1 << 1) public static let isAnimated = StickerPackCollectionInfoFlags(rawValue: 1 << 2) public static let isVideo = StickerPackCollectionInfoFlags(rawValue: 1 << 3) + public static let isEmoji = StickerPackCollectionInfoFlags(rawValue: 1 << 4) } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_SynchronizeInstalledStickerPacksOperations.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_SynchronizeInstalledStickerPacksOperations.swift index c7ad51c754..03ff97549f 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_SynchronizeInstalledStickerPacksOperations.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_SynchronizeInstalledStickerPacksOperations.swift @@ -4,6 +4,7 @@ import Postbox public enum SynchronizeInstalledStickerPacksOperationNamespace: Int32 { case stickers = 0 case masks = 1 + case emoji } public final class SynchronizeInstalledStickerPacksOperation: PostboxCoding { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index 48bf5de03f..66606f6fb3 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift @@ -51,6 +51,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case setChatTheme(emoji: String) case joinedByRequest case webViewData(String) + case giftPremium(currency: String, amount: Int64, months: Int32) public init(decoder: PostboxDecoder) { let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0) @@ -119,6 +120,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { self = .joinedByRequest case 26: self = .webViewData(decoder.decodeStringForKey("t", orElse: "")) + case 27: + self = .giftPremium(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), months: decoder.decodeInt32ForKey("months", orElse: 0)) default: self = .unknown } @@ -243,6 +246,11 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case let .webViewData(text): encoder.encodeInt32(26, forKey: "_rawValue") encoder.encodeString(text, forKey: "t") + case let .giftPremium(currency, amount, months): + encoder.encodeInt32(27, forKey: "_rawValue") + encoder.encodeString(currency, forKey: "currency") + encoder.encodeInt64(amount, forKey: "amount") + encoder.encodeInt32(months, forKey: "months") } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index c01106354f..dcb6ebf8b2 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -11,13 +11,15 @@ private let typeHasLinkedStickers: Int32 = 6 private let typeHintFileIsLarge: Int32 = 7 private let typeHintIsValidated: Int32 = 8 private let typeNoPremium: Int32 = 9 +private let typeCustomEmoji: Int32 = 10 -public enum StickerPackReference: PostboxCoding, Hashable, Equatable { +public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { case id(id: Int64, accessHash: Int64) case name(String) case animatedEmoji case dice(String) case animatedEmojiAnimations + case premiumGifts public init(decoder: PostboxDecoder) { switch decoder.decodeInt32ForKey("r", orElse: 0) { @@ -31,12 +33,37 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable { self = .dice(decoder.decodeStringForKey("e", orElse: "🎲")) case 4: self = .animatedEmojiAnimations + case 5: + self = .premiumGifts default: self = .name("") assertionFailure() } } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: StringCodingKey.self) + + let discriminator = try container.decode(Int32.self, forKey: "r") + switch discriminator { + case 0: + self = .id(id: try container.decode(Int64.self, forKey: "i"), accessHash: try container.decode(Int64.self, forKey: "h")) + case 1: + self = .name(try container.decode(String.self, forKey: "n")) + case 2: + self = .animatedEmoji + case 3: + self = .dice((try? container.decode(String.self, forKey: "e")) ?? "🎲") + case 4: + self = .animatedEmojiAnimations + case 5: + self = .premiumGifts + default: + self = .name("") + assertionFailure() + } + } + public func encode(_ encoder: PostboxEncoder) { switch self { case let .id(id, accessHash): @@ -53,6 +80,31 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable { encoder.encodeString(emoji, forKey: "e") case .animatedEmojiAnimations: encoder.encodeInt32(4, forKey: "r") + case .premiumGifts: + encoder.encodeInt32(5, forKey: "r") + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: StringCodingKey.self) + + switch self { + case let .id(id, accessHash): + try container.encode(0 as Int32, forKey: "r") + try container.encode(id, forKey: "i") + try container.encode(accessHash, forKey: "h") + case let .name(name): + try container.encode(1 as Int32, forKey: "r") + try container.encode(name, forKey: "n") + case .animatedEmoji: + try container.encode(2 as Int32, forKey: "r") + case let .dice(emoji): + try container.encode(3 as Int32, forKey: "r") + try container.encode(emoji, forKey: "e") + case .animatedEmojiAnimations: + try container.encode(4 as Int32, forKey: "r") + case .premiumGifts: + try container.encode(5 as Int32, forKey: "r") } } @@ -88,6 +140,12 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable { } else { return false } + case .premiumGifts: + if case .premiumGifts = rhs { + return true + } else { + return false + } } } } @@ -146,6 +204,7 @@ public enum TelegramMediaFileAttribute: PostboxCoding { case hintFileIsLarge case hintIsValidated case NoPremium + case CustomEmoji(isPremium: Bool, alt: String, packReference: StickerPackReference?) public init(decoder: PostboxDecoder) { let type: Int32 = decoder.decodeInt32ForKey("t", orElse: 0) @@ -175,6 +234,8 @@ public enum TelegramMediaFileAttribute: PostboxCoding { self = .hintIsValidated case typeNoPremium: self = .NoPremium + case typeCustomEmoji: + self = .CustomEmoji(isPremium: decoder.decodeBoolForKey("ip", orElse: true), alt: decoder.decodeStringForKey("dt", orElse: ""), packReference: decoder.decodeObjectForKey("pr", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference) default: preconditionFailure() } @@ -231,6 +292,15 @@ public enum TelegramMediaFileAttribute: PostboxCoding { encoder.encodeInt32(typeHintIsValidated, forKey: "t") case .NoPremium: encoder.encodeInt32(typeNoPremium, forKey: "t") + case let .CustomEmoji(isPremium, alt, packReference): + encoder.encodeInt32(typeCustomEmoji, forKey: "t") + encoder.encodeBool(isPremium, forKey: "ip") + encoder.encodeString(alt, forKey: "dt") + if let packReference = packReference { + encoder.encodeObject(packReference, forKey: "pr") + } else { + encoder.encodeNil(forKey: "pr") + } } } } @@ -535,6 +605,40 @@ public final class TelegramMediaFile: Media, Equatable, Codable { return false } + public var isCustomEmoji: Bool { + var hasSticker = false + for attribute in self.attributes { + if case .CustomEmoji = attribute { + hasSticker = true + break + } + } + return hasSticker + } + + public var isPremiumEmoji: Bool { + for attribute in self.attributes { + if case let .CustomEmoji(isPremium, _, _) = attribute { + return isPremium + } + } + return false + } + + public var isVideoEmoji: Bool { + if self.mimeType == "video/webm" { + var hasSticker = false + for attribute in self.attributes { + if case .CustomEmoji = attribute { + hasSticker = true + break + } + } + return hasSticker + } + return false + } + public var hasLinkedStickers: Bool { for attribute in self.attributes { if case .HasLinkedStickers = attribute { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift index 6906d5ba9f..74dfbbc048 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift @@ -21,7 +21,7 @@ public enum MessageTextEntityType: Equatable { case Underline case BankCard case Spoiler - case AnimatedEmoji(MediaId?) + case CustomEmoji(stickerPack: StickerPackReference?, fileId: Int64) case Custom(type: CustomEntityType) } @@ -73,7 +73,8 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { case 17: self.type = .Spoiler case 18: - self.type = .AnimatedEmoji(decoder.decodeObjectForKey("mediaId") as? MediaId) + let stickerPack = decoder.decodeObjectForKey("s", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference + self.type = .CustomEmoji(stickerPack: stickerPack, fileId: decoder.decodeInt64ForKey("f", orElse: 0)) case Int32.max: self.type = .Custom(type: decoder.decodeInt32ForKey("type", orElse: 0)) default: @@ -130,7 +131,7 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { case 17: self.type = .Spoiler case 18: - self.type = .AnimatedEmoji(try? container.decode(MediaId.self, forKey: "mediaId")) + self.type = .CustomEmoji(stickerPack: try container.decodeIfPresent(StickerPackReference.self, forKey: "s"), fileId: try container.decode(Int64.self, forKey: "f")) case Int32.max: let customType: Int32 = (try? container.decode(Int32.self, forKey: "type")) ?? 0 self.type = .Custom(type: customType) @@ -181,13 +182,14 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { encoder.encodeInt32(16, forKey: "_rawValue") case .Spoiler: encoder.encodeInt32(17, forKey: "_rawValue") - case let .AnimatedEmoji(mediaId): + case let .CustomEmoji(stickerPack, fileId): encoder.encodeInt32(18, forKey: "_rawValue") - if let mediaId = mediaId { - encoder.encodeObject(mediaId, forKey: "mediaId") - } else { - encoder.encodeNil(forKey: "mediaId") - } + if let stickerPack = stickerPack { + encoder.encodeObject(stickerPack, forKey: "s") + } else { + encoder.encodeNil(forKey: "s") + } + encoder.encodeInt64(fileId, forKey: "f") case let .Custom(type): encoder.encodeInt32(Int32.max, forKey: "_rawValue") encoder.encodeInt32(type, forKey: "type") @@ -238,11 +240,10 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { try container.encode(16 as Int32, forKey: "_rawValue") case .Spoiler: try container.encode(17 as Int32, forKey: "_rawValue") - case let .AnimatedEmoji(mediaId): + case let .CustomEmoji(stickerPack, fileId): try container.encode(18 as Int32, forKey: "_rawValue") - if let mediaId = mediaId { - try container.encode(mediaId, forKey: "mediaId") - } + try container.encodeIfPresent(stickerPack, forKey: "s") + try container.encode(fileId, forKey: "f") case let .Custom(type): try container.encode(Int32.max as Int32, forKey: "_rawValue") try container.encode(type as Int32, forKey: "type") @@ -270,6 +271,23 @@ public class TextEntitiesMessageAttribute: MessageAttribute, Equatable { return result } + public var associatedMediaIds: [MediaId] { + var result: [MediaId] = [] + for entity in self.entities { + switch entity.type { + case let .CustomEmoji(_, fileId): + result.append(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) + default: + break + } + } + if result.isEmpty { + return result + } else { + return Array(Set(result)) + } + } + public init(entities: [MessageTextEntity]) { self.entities = entities } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index 49f8de5810..c602bd5719 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -247,7 +247,8 @@ private class AdMessagesHistoryContextImpl { media: self.media, peers: messagePeers, associatedMessages: SimpleDictionary(), - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ChatList.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ChatList.swift index c3fb924f16..ce77b1e1d0 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/ChatList.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/ChatList.swift @@ -16,6 +16,16 @@ public final class EngineChatList { case later(than: EngineChatList.Item.Index?) case earlier(than: EngineChatList.Item.Index?) } + + public struct Draft { + public var text: String + public var entities: [MessageTextEntity] + + public init(text: String, entities: [MessageTextEntity]) { + self.text = text + self.entities = entities + } + } public final class Item { public typealias Index = ChatListIndex @@ -24,7 +34,7 @@ public final class EngineChatList { public let messages: [EngineMessage] public let readCounters: EnginePeerReadCounters? public let isMuted: Bool - public let draftText: String? + public let draft: Draft? public let renderedPeer: EngineRenderedPeer public let presence: EnginePeer.Presence? public let hasUnseenMentions: Bool @@ -37,7 +47,7 @@ public final class EngineChatList { messages: [EngineMessage], readCounters: EnginePeerReadCounters?, isMuted: Bool, - draftText: String?, + draft: Draft?, renderedPeer: EngineRenderedPeer, presence: EnginePeer.Presence?, hasUnseenMentions: Bool, @@ -49,7 +59,7 @@ public final class EngineChatList { self.messages = messages self.readCounters = readCounters self.isMuted = isMuted - self.draftText = draftText + self.draft = draft self.renderedPeer = renderedPeer self.presence = presence self.hasUnseenMentions = hasUnseenMentions @@ -209,11 +219,11 @@ extension EngineChatList.Item { convenience init?(_ entry: ChatListEntry) { switch entry { case let .MessageEntry(index, messages, readState, isRemovedFromTotalUnreadCount, embeddedState, renderedPeer, presence, tagSummaryInfo, hasFailed, isContact): - var draftText: String? + var draft: EngineChatList.Draft? if let embeddedState = embeddedState, let _ = embeddedState.overrideChatTimestamp { if let opaqueState = _internal_decodeStoredChatInterfaceState(state: embeddedState) { if let text = opaqueState.synchronizeableInputState?.text { - draftText = text + draft = EngineChatList.Draft(text: text, entities: opaqueState.synchronizeableInputState?.entities ?? []) } } } @@ -239,7 +249,7 @@ extension EngineChatList.Item { messages: messages.map(EngineMessage.init), readCounters: readState.flatMap(EnginePeerReadCounters.init), isMuted: isRemovedFromTotalUnreadCount, - draftText: draftText, + draft: draft, renderedPeer: EngineRenderedPeer(renderedPeer), presence: presence.flatMap(EnginePeer.Presence.init), hasUnseenMentions: hasUnseenMentions, diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Message.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Message.swift index ef74b8b0d0..2d62873e3b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Message.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Message.swift @@ -75,6 +75,9 @@ public final class EngineMessage { public var associatedMessageIds: [EngineMessage.Id] { return self.impl.associatedMessageIds } + public var associatedMedia: [MediaId: Media] { + return self.impl.associatedMedia + } public var index: MessageIndex { return self.impl.index @@ -100,7 +103,8 @@ public final class EngineMessage { media: [EngineMedia], peers: [EnginePeer.Id: EnginePeer], associatedMessages: [EngineMessage.Id: EngineMessage], - associatedMessageIds: [EngineMessage.Id] + associatedMessageIds: [EngineMessage.Id], + associatedMedia: [MediaId: Media] ) { var mappedPeers: [PeerId: Peer] = [:] for (id, peer) in peers { @@ -132,7 +136,8 @@ public final class EngineMessage { media: media.map { $0._asMedia() }, peers: SimpleDictionary(mappedPeers), associatedMessages: SimpleDictionary(mappedAssociatedMessages), - associatedMessageIds: associatedMessageIds + associatedMessageIds: associatedMessageIds, + associatedMedia: associatedMedia ) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift index f9ebfee534..b8001dea16 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/OutgoingMessageWithChatContextResult.swift @@ -41,19 +41,19 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe return true } if let media: Media = internalReference.file ?? internalReference.image { - return .message(text: caption, attributes: filteredAttributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: filteredAttributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else { - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else if let file = internalReference.file, internalReference.type == "gif" { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else if let image = internalReference.image { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else if let file = internalReference.file { - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { return nil } @@ -65,9 +65,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe let thumbnailResource = thumbnail.resource let imageDimensions = thumbnail.dimensions ?? PixelDimensions(width: 128, height: 128) let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: [TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []) - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } else if externalReference.type == "document" || externalReference.type == "gif" || externalReference.type == "audio" || externalReference.type == "voice" { var videoThumbnails: [TelegramMediaFile.VideoThumbnail] = [] @@ -127,9 +127,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe } let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: nil, mimeType: externalReference.content?.mimeType ?? "application/binary", size: nil, attributes: fileAttributes) - return .message(text: caption, attributes: attributes, mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } else { - return .message(text: caption, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } case let .text(text, entities, _, replyMarkup): @@ -139,21 +139,21 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, botId: Pe if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .mapLocation(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .contact(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) case let .invoice(media, replyMarkup): if let replyMarkup = replyMarkup { attributes.append(replyMarkup) } - return .message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) + return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift index e26a6025b3..adea19cb57 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/RequestStartBot.swift @@ -25,7 +25,7 @@ func _internal_requestStartBot(account: Account, botPeerId: PeerId, payload: Str } } } else { - return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> mapToSignal { _ -> Signal in + return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) |> mapToSignal { _ -> Signal in return .complete() } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index f45b440830..830f9c0537 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -85,8 +85,8 @@ public extension TelegramEngine { return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId) } - public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { - return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) + public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal { + return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime) } public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?) -> Signal { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index b7e51a0c15..2da50b9aef 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -10,22 +10,47 @@ public enum AssignAppStoreTransactionError { case serverProvided } -func _internal_sendAppStoreReceipt(account: Account, receipt: Data, restore: Bool) -> Signal { - var flags: Int32 = 0 - if restore { - flags |= (1 << 0) - } - return account.network.request(Api.functions.payments.assignAppStoreTransaction(flags: flags, receipt: Buffer(data: receipt))) - |> mapError { error -> AssignAppStoreTransactionError in - if error.errorCode == 406 { - return .serverProvided - } else { - return .generic +public enum AppStoreTransactionPurpose { + case subscription + case gift(peerId: EnginePeer.Id, currency: String, amount: Int64) + case restore +} + +func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: AppStoreTransactionPurpose) -> Signal { + var purposeSignal: Signal + switch purpose { + case .subscription, .restore: + var flags: Int32 = 0 + if case .restore = purpose { + flags |= (1 << 0) + } + purposeSignal = .single(.inputStorePaymentPremiumSubscription(flags: flags)) + case let .gift(peerId, currency, amount): + purposeSignal = account.postbox.loadedPeerWithId(peerId) + |> mapToSignal { peer -> Signal in + if let inputUser = apiInputUser(peer) { + return .single(.inputStorePaymentGiftPremium(userId: inputUser, currency: currency, amount: amount)) + } else { + return .complete() + } } } - |> mapToSignal { updates -> Signal in - account.stateManager.addUpdates(updates) - return .complete() + + return purposeSignal + |> castError(AssignAppStoreTransactionError.self) + |> mapToSignal { purpose -> Signal in + return account.network.request(Api.functions.payments.assignAppStoreTransaction(receipt: Buffer(data: receipt), purpose: purpose)) + |> mapError { error -> AssignAppStoreTransactionError in + if error.errorCode == 406 { + return .serverProvided + } else { + return .generic + } + } + |> mapToSignal { updates -> Signal in + account.stateManager.addUpdates(updates) + return .complete() + } } } @@ -33,17 +58,39 @@ public enum RestoreAppStoreReceiptError { case generic } -func _internal_canPurchasePremium(account: Account) -> Signal { - return account.network.request(Api.functions.payments.canPurchasePremium()) - |> map { result -> Bool in - switch result { - case .boolTrue: - return true - case .boolFalse: - return false +func _internal_canPurchasePremium(account: Account, purpose: AppStoreTransactionPurpose) -> Signal { + var purposeSignal: Signal + switch purpose { + case .subscription, .restore: + var flags: Int32 = 0 + if case .restore = purpose { + flags |= (1 << 0) + } + purposeSignal = .single(.inputStorePaymentPremiumSubscription(flags: flags)) + case let .gift(peerId, currency, amount): + purposeSignal = account.postbox.loadedPeerWithId(peerId) + |> mapToSignal { peer -> Signal in + if let inputUser = apiInputUser(peer) { + return .single(.inputStorePaymentGiftPremium(userId: inputUser, currency: currency, amount: amount)) + } else { + return .complete() + } } } - |> `catch` { _ -> Signal in - return.single(false) + + return purposeSignal + |> mapToSignal { purpose -> Signal in + return account.network.request(Api.functions.payments.canPurchasePremium(purpose: purpose)) + |> map { result -> Bool in + switch result { + case .boolTrue: + return true + case .boolFalse: + return false + } + } + |> `catch` { _ -> Signal in + return.single(false) + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index 4518080812..da5c02c6d6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -119,7 +119,22 @@ public struct BotPaymentForm : Equatable { public let url: String public let nativeProvider: BotPaymentNativeProvider? public let savedInfo: BotPaymentRequestedInfo? - public let savedCredentials: BotPaymentSavedCredentials? + public let savedCredentials: [BotPaymentSavedCredentials] + public let additionalPaymentMethods: [BotPaymentMethod] +} + +public struct BotPaymentMethod: Equatable { + public let url: String + public let title: String +} + +extension BotPaymentMethod { + init(apiPaymentFormMethod: Api.PaymentFormMethod) { + switch apiPaymentFormMethod { + case let .paymentFormMethod(url, title): + self.init(url: url, title: title) + } + } } public enum BotPaymentFormRequestError { @@ -213,7 +228,7 @@ func _internal_fetchBotPaymentInvoice(postbox: Postbox, network: Network, source |> mapToSignal { result -> Signal in return postbox.transaction { transaction -> TelegramMediaInvoice in switch result { - case let .paymentForm(_, _, _, title, description, photo, invoice, _, _, _, _, _, _, _): + case let .paymentForm(_, _, _, title, description, photo, invoice, _, _, _, _, _, _, _, _): let parsedInvoice = BotPaymentInvoice(apiInvoice: invoice) var parsedFlags = TelegramMediaInvoiceFlags() @@ -266,11 +281,11 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B |> mapToSignal { result -> Signal in return postbox.transaction { transaction -> BotPaymentForm in switch result { - case let .paymentForm(flags, id, botId, title, description, photo, invoice, providerId, url, nativeProvider, nativeParams, savedInfo, savedCredentials, apiUsers): + case let .paymentForm(flags, id, botId, title, description, photo, invoice, providerId, url, nativeProvider, nativeParams, additionalMethods, savedInfo, savedCredentials, apiUsers): let _ = title let _ = description let _ = photo - + var peers: [Peer] = [] for user in apiUsers { let parsed = TelegramUser(user: user) @@ -289,14 +304,15 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B } } let parsedSavedInfo = savedInfo.flatMap(BotPaymentRequestedInfo.init) - var parsedSavedCredentials: BotPaymentSavedCredentials? - if let savedCredentials = savedCredentials { + let parsedSavedCredentials = savedCredentials?.map({ savedCredentials -> BotPaymentSavedCredentials in switch savedCredentials { case let .paymentSavedCredentialsCard(id, title): - parsedSavedCredentials = .card(id: id, title: title) + return .card(id: id, title: title) } - } - return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials) + }) ?? [] + + let additionalPaymentMethods = additionalMethods?.map({ BotPaymentMethod(apiPaymentFormMethod: $0) }) ?? [] + return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials, additionalPaymentMethods: additionalPaymentMethods) } } |> mapError { _ -> BotPaymentFormRequestError in } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index 8afeb78d59..5906aa0687 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -38,12 +38,12 @@ public extension TelegramEngine { return _internal_clearBotPaymentInfo(network: self.account.network, info: info) } - public func sendAppStoreReceipt(receipt: Data, restore: Bool) -> Signal { - return _internal_sendAppStoreReceipt(account: self.account, receipt: receipt, restore: restore) + public func sendAppStoreReceipt(receipt: Data, purpose: AppStoreTransactionPurpose) -> Signal { + return _internal_sendAppStoreReceipt(account: self.account, receipt: receipt, purpose: purpose) } - public func canPurchasePremium() -> Signal { - return _internal_canPurchasePremium(account: self.account) + public func canPurchasePremium(purpose: AppStoreTransactionPurpose) -> Signal { + return _internal_canPurchasePremium(account: self.account, purpose: purpose) } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 9cafdf198b..31c2abda50 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -216,7 +216,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee } switch fullUser { - case let .userFull(_, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _): + case let .userFull(_, _, _, _, _, userFullNotifySettings, _, _, _, _, _, _, _, _, _, _): updatePeers(transaction: transaction, peers: peers, update: { previous, updated -> Peer in if previous?.id == accountPeerId, let accountUser = accountUser, let user = TelegramUser.merge(previous as? TelegramUser, rhs: accountUser) { return user @@ -234,16 +234,18 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee previous = CachedUserData() } switch fullUser { - case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, profilePhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _): + case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, profilePhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions): let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:)) let isBlocked = (userFullFlags & (1 << 0)) != 0 let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0 let videoCallsAvailable = (userFullFlags & (1 << 13)) != 0 - + let voiceMessagesAvailable = (userFullFlags & (1 << 20)) == 0 + let callsPrivate = (userFullFlags & (1 << 5)) != 0 let canPinMessages = (userFullFlags & (1 << 7)) != 0 let pinnedMessageId = userFullPinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }) - + + let peerStatusSettings = PeerStatusSettings(apiSettings: userFullSettings) let hasScheduledMessages = (userFullFlags & 1 << 12) != 0 @@ -252,10 +254,26 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee let photo = profilePhoto.flatMap { telegramMediaImageFromApiPhoto($0) } + let premiumGiftOptions: [CachedPremiumGiftOption] + if let userPremiumGiftOptions = userPremiumGiftOptions { + premiumGiftOptions = userPremiumGiftOptions.map { apiOption in + let option: CachedPremiumGiftOption + switch apiOption { + case let .premiumGiftOption(_, months, currency, amount, botUrl, storeProduct): + option = CachedPremiumGiftOption(months: months, currency: currency, amount: amount, botUrl: botUrl, storeProductId: storeProduct) + } + return option + } + } else { + premiumGiftOptions = [] + } + return previous.withUpdatedAbout(userFullAbout).withUpdatedBotInfo(botInfo).withUpdatedCommonGroupCount(userFullCommonChatsCount).withUpdatedIsBlocked(isBlocked).withUpdatedVoiceCallsAvailable(voiceCallsAvailable).withUpdatedVideoCallsAvailable(videoCallsAvailable).withUpdatedCallsPrivate(callsPrivate).withUpdatedCanPinMessages(canPinMessages).withUpdatedPeerStatusSettings(peerStatusSettings).withUpdatedPinnedMessageId(pinnedMessageId).withUpdatedHasScheduledMessages(hasScheduledMessages) .withUpdatedAutoremoveTimeout(autoremoveTimeout) .withUpdatedThemeEmoticon(userFullThemeEmoticon) .withUpdatedPhoto(photo) + .withUpdatedPremiumGiftOptions(premiumGiftOptions) + .withUpdatedVoiceMessagesAvailable(voiceMessagesAvailable) } }) } @@ -526,9 +544,11 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee let stickerPack: StickerPackCollectionInfo? = stickerSet.flatMap { apiSet -> StickerPackCollectionInfo in let namespace: ItemCollectionId.Namespace switch apiSet { - case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _): + case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 3)) != 0 { namespace = Namespaces.ItemCollection.CloudMaskPacks + } else if (flags & (1 << 7)) != 0 { + namespace = Namespaces.ItemCollection.CloudEmojiPacks } else { namespace = Namespaces.ItemCollection.CloudStickerPacks } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift index 5fc712fd8c..468b557688 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift @@ -13,13 +13,14 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal `catch` { _ in return .complete() } - |> mapToSignal { lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, voiceCallP2P, profilePhotoPrivacy, forwardPrivacy, phoneNumberPrivacy, phoneDiscoveryPrivacy, autoremoveTimeout, globalPrivacySettings -> Signal in + |> mapToSignal { lastSeenPrivacy, groupPrivacy, voiceCallPrivacy, voiceCallP2P, profilePhotoPrivacy, forwardPrivacy, phoneNumberPrivacy, phoneDiscoveryPrivacy, voiceMessagesPrivacy, autoremoveTimeout, globalPrivacySettings -> Signal in let accountTimeoutSeconds: Int32 switch autoremoveTimeout { case let .accountDaysTTL(days): @@ -33,6 +34,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal Signal Signal map { result -> [ArchivedStickerPackItem] in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift index 8c71c80536..6a0b558e0e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift @@ -124,6 +124,20 @@ func _internal_cachedStickerPack(postbox: Postbox, network: Network, reference: } else { return (.fetching, true, nil) } + case .premiumGifts: + let namespace = Namespaces.ItemCollection.CloudPremiumGifts + let id: ItemCollectionId.Id = 0 + if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info { + previousHash = cached.hash + let current: CachedStickerPackResult = .result(info, cached.items, false) + if cached.hash != info.hash { + return (current, true, previousHash) + } else { + return (current, false, previousHash) + } + } else { + return (.fetching, true, nil) + } } } |> mapToSignal { result, loadRemote, previousHash in @@ -154,7 +168,7 @@ func _internal_cachedStickerPack(postbox: Postbox, network: Network, reference: } func cachedStickerPack(transaction: Transaction, reference: StickerPackReference) -> (StickerPackCollectionInfo, [StickerPackItem], Bool)? { - let namespaces: [Int32] = [Namespaces.ItemCollection.CloudStickerPacks, Namespaces.ItemCollection.CloudMaskPacks] + let namespaces: [Int32] = [Namespaces.ItemCollection.CloudStickerPacks, Namespaces.ItemCollection.CloudMaskPacks, Namespaces.ItemCollection.CloudEmojiPacks] switch reference { case let .id(id, _): for namespace in namespaces { @@ -220,6 +234,18 @@ func cachedStickerPack(transaction: Transaction, reference: StickerPackReference if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info { return (info, cached.items, false) } + case .premiumGifts: + let namespace = Namespaces.ItemCollection.CloudPremiumGifts + let id: ItemCollectionId.Id = 0 + if let currentInfo = transaction.getItemCollectionInfo(collectionId: ItemCollectionId(namespace: namespace, id: id)) as? StickerPackCollectionInfo { + let items = transaction.getItemCollectionItems(collectionId: ItemCollectionId(namespace: namespace, id: id)) + if !items.isEmpty { + return (currentInfo, items.compactMap { $0 as? StickerPackItem }, true) + } + } + if let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedStickerPacks, key: CachedStickerPack.cacheKey(ItemCollectionId(namespace: namespace, id: id))))?.get(CachedStickerPack.self), let info = cached.info { + return (info, cached.items, false) + } } return nil } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift index 3331fa05b5..2ffeadd0c1 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift @@ -170,9 +170,11 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri case let .stickerSet(set, packs, documents): let namespace: ItemCollectionId.Namespace switch set { - case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _): + case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 3)) != 0 { namespace = Namespaces.ItemCollection.CloudMaskPacks + } else if (flags & (1 << 7)) != 0 { + namespace = Namespaces.ItemCollection.CloudEmojiPacks } else { namespace = Namespaces.ItemCollection.CloudStickerPacks } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/InlineStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/InlineStickers.swift new file mode 100644 index 0000000000..f13c9156dc --- /dev/null +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/InlineStickers.swift @@ -0,0 +1,5 @@ +import Foundation +import Postbox +import TelegramApi +import SwiftSignalKit + diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift index 0abcc50461..39f7ef1f0d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift @@ -20,6 +20,8 @@ extension StickerPackReference { return .inputStickerSetDice(emoticon: emoji) case .animatedEmojiAnimations: return .inputStickerSetAnimatedEmojiAnimations + case .premiumGifts: + return .inputStickerSetPremiumGifts } } } @@ -49,9 +51,11 @@ func updatedRemoteStickerPack(postbox: Postbox, network: Network, reference: Sti case let .stickerSet(set, packs, documents): let namespace: ItemCollectionId.Namespace switch set { - case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _): + case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _, _): if (flags & (1 << 3)) != 0 { namespace = Namespaces.ItemCollection.CloudMaskPacks + } else if (flags & (1 << 7)) != 0 { + namespace = Namespaces.ItemCollection.CloudEmojiPacks } else { namespace = Namespaces.ItemCollection.CloudStickerPacks } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift index 7d61a5a8f3..954e7ef206 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/SearchStickers.swift @@ -306,7 +306,7 @@ func _internal_searchStickerSetsRemotely(network: Network, query: String) -> Sig case let .foundStickerSets(_, sets: sets): var result = FoundStickerSets() for set in sets { - let parsed = parsePreviewStickerSet(set) + let parsed = parsePreviewStickerSet(set, namespace: Namespaces.ItemCollection.CloudStickerPacks) let values = parsed.1.map({ ItemCollectionViewEntry(index: ItemCollectionViewEntryIndex(collectionIndex: index, collectionId: parsed.0.id, itemIndex: $0.index), item: $0) }) result = result.withUpdatedInfosAndEntries(infos: [(parsed.0.id, parsed.0, parsed.1.first, false)], entries: values) index += 1 diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift index eecdae4f7b..4fb16e89f7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift @@ -32,7 +32,7 @@ func telegramStickerPackThumbnailRepresentationFromApiSizes(datacenterId: Int32, extension StickerPackCollectionInfo { convenience init(apiSet: Api.StickerSet, namespace: ItemCollectionId.Namespace) { switch apiSet { - case let .stickerSet(flags, _, id, accessHash, title, shortName, thumbs, thumbDcId, thumbVersion, count, nHash): + case let .stickerSet(flags, _, id, accessHash, title, shortName, thumbs, thumbDcId, thumbVersion, thumbDocumentId, count, nHash): var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags() if (flags & (1 << 2)) != 0 { setFlags.insert(.isOfficial) @@ -46,6 +46,9 @@ extension StickerPackCollectionInfo { if (flags & (1 << 6)) != 0 { setFlags.insert(.isVideo) } + if (flags & (1 << 7)) != 0 { + setFlags.insert(.isEmoji) + } var thumbnailRepresentation: TelegramMediaImageRepresentation? var immediateThumbnailData: Data? @@ -54,6 +57,8 @@ extension StickerPackCollectionInfo { thumbnailRepresentation = representations.first immediateThumbnailData = data } + + let _ = thumbDocumentId self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, thumbnail: thumbnailRepresentation, immediateThumbnailData: immediateThumbnailData, hash: nHash, count: count) } @@ -100,7 +105,7 @@ func _internal_stickerPacksAttachedToMedia(account: Account, media: AnyMediaRefe |> map { result -> [StickerPackReference] in return result.map { pack in switch pack { - case let .stickerSetCovered(set, _), let .stickerSetMultiCovered(set, _): + case let .stickerSetCovered(set, _), let .stickerSetMultiCovered(set, _), let .stickerSetFullCovered(set, _, _): let info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks) return .id(id: info.id.id, accessHash: info.accessHash) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift index 4c40991bdd..1dabaf79ed 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift @@ -3,7 +3,7 @@ import Postbox import SwiftSignalKit -func _internal_addStickerPackInteractively(postbox: Postbox, info: StickerPackCollectionInfo, items: [ItemCollectionItem], positionInList: Int? = nil) -> Signal { +func _internal_addStickerPackInteractively(postbox: Postbox, info: StickerPackCollectionInfo, items: [StickerPackItem], positionInList: Int? = nil) -> Signal { return postbox.transaction { transaction -> Void in let namespace: SynchronizeInstalledStickerPacksOperationNamespace? switch info.id.namespace { @@ -11,6 +11,8 @@ func _internal_addStickerPackInteractively(postbox: Postbox, info: StickerPackCo namespace = .stickers case Namespaces.ItemCollection.CloudMaskPacks: namespace = .masks + case Namespaces.ItemCollection.CloudEmojiPacks: + namespace = .emoji default: namespace = nil } @@ -31,7 +33,12 @@ func _internal_addStickerPackInteractively(postbox: Postbox, info: StickerPackCo } else { updatedInfos.insert(mappedInfo, at: 0) } - transaction.replaceItemCollectionItems(collectionId: mappedInfo.id, items: items) + + var indexedItems: [ItemCollectionItem] = [] + for item in items { + indexedItems.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(indexedItems.count), id: item.index.id), file: item.file, indexKeys: item.indexKeys)) + } + transaction.replaceItemCollectionItems(collectionId: mappedInfo.id, items: indexedItems) } transaction.replaceItemCollectionInfos(namespace: mappedInfo.id.namespace, itemCollectionInfos: updatedInfos.map { ($0.id, $0) }) } @@ -57,6 +64,8 @@ func _internal_removeStickerPacksInteractively(postbox: Postbox, ids: [ItemColle namespace = .stickers case Namespaces.ItemCollection.CloudMaskPacks: namespace = .masks + case Namespaces.ItemCollection.CloudEmojiPacks: + namespace = .emoji default: namespace = nil } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift index 10dc4e700a..ef411ee005 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift @@ -43,6 +43,9 @@ func _internal_requestStickerSet(postbox: Postbox, network: Network, reference: case .animatedEmojiAnimations: collectionId = nil input = .inputStickerSetAnimatedEmojiAnimations + case .premiumGifts: + collectionId = nil + input = .inputStickerSetPremiumGifts } let localSignal: (ItemCollectionId) -> Signal<(ItemCollectionInfo, [ItemCollectionItem])?, NoError> = { collectionId in @@ -66,7 +69,7 @@ func _internal_requestStickerSet(postbox: Postbox, network: Network, reference: info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks) switch set { - case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _): + case let .stickerSet(flags, _, _, _, _, _, _, _, _, _, _, _): installed = (flags & (1 << 0) != 0) } @@ -140,64 +143,69 @@ public final class CoveredStickerSet : Equatable { func _internal_installStickerSetInteractively(account: Account, info: StickerPackCollectionInfo, items: [ItemCollectionItem]) -> Signal { return account.network.request(Api.functions.messages.installStickerSet(stickerset: .inputStickerSetID(id: info.id.id, accessHash: info.accessHash), archived: .boolFalse)) |> mapError { _ -> InstallStickerSetError in return .generic - } |> mapToSignal { result -> Signal in - let addResult:InstallStickerSetResult - switch result { - case .stickerSetInstallResultSuccess: - addResult = .successful - case let .stickerSetInstallResultArchive(sets: archived): - var coveredSets:[CoveredStickerSet] = [] - for archived in archived { - let apiDocuments:[Api.Document] - let apiSet:Api.StickerSet - switch archived { - case let .stickerSetCovered(set: set, cover: cover): - apiSet = set - apiDocuments = [cover] - case let .stickerSetMultiCovered(set: set, covers: covers): - apiSet = set - apiDocuments = covers + } + |> mapToSignal { result -> Signal in + let addResult:InstallStickerSetResult + switch result { + case .stickerSetInstallResultSuccess: + addResult = .successful + case let .stickerSetInstallResultArchive(sets: archived): + var coveredSets:[CoveredStickerSet] = [] + for archived in archived { + let apiDocuments:[Api.Document] + let apiSet:Api.StickerSet + switch archived { + case let .stickerSetCovered(set: set, cover: cover): + apiSet = set + apiDocuments = [cover] + case let .stickerSetMultiCovered(set: set, covers: covers): + apiSet = set + apiDocuments = covers + case let .stickerSetFullCovered(set, _, documents): + apiSet = set + apiDocuments = documents + } + + let info = StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks) + + var items:[StickerPackItem] = [] + for apiDocument in apiDocuments { + if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id { + items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: [])) } - - let info = StickerPackCollectionInfo(apiSet: apiSet, namespace: Namespaces.ItemCollection.CloudStickerPacks) - - var items:[StickerPackItem] = [] - for apiDocument in apiDocuments { - if let file = telegramMediaFileFromApiDocument(apiDocument), let id = file.id { - items.append(StickerPackItem(index: ItemCollectionItemIndex(index: Int32(items.count), id: id.id), file: file, indexKeys: [])) + } + coveredSets.append(CoveredStickerSet(info: info, items: items)) + } + addResult = .archived(coveredSets) + } + + + return account.postbox.transaction { transaction -> Void in + var collections = transaction.getCollectionsItems(namespace: info.id.namespace) + + var removableIndexes:[Int] = [] + for i in 0 ..< collections.count { + if collections[i].0 == info.id { + removableIndexes.append(i) + } + if case let .archived(sets) = addResult { + for set in sets { + if collections[i].0 == set.info.id { + removableIndexes.append(i) } } - coveredSets.append(CoveredStickerSet(info: info, items: items)) } - addResult = .archived(coveredSets) } + for index in removableIndexes.reversed() { + collections.remove(at: index) + } - return account.postbox.transaction { transaction -> Void in - var collections = transaction.getCollectionsItems(namespace: info.id.namespace) - - var removableIndexes:[Int] = [] - for i in 0 ..< collections.count { - if collections[i].0 == info.id { - removableIndexes.append(i) - } - if case let .archived(sets) = addResult { - for set in sets { - if collections[i].0 == set.info.id { - removableIndexes.append(i) - } - } - } - } - - for index in removableIndexes.reversed() { - collections.remove(at: index) - } - - collections.insert((info.id, info, items), at: 0) - - transaction.replaceItemCollections(namespace: info.id.namespace, itemCollections: collections) - } |> map { _ in return addResult} |> mapError { _ -> InstallStickerSetError in } + collections.insert((info.id, info, items), at: 0) + + transaction.replaceItemCollections(namespace: info.id.namespace, itemCollections: collections) + } + |> map { _ in return addResult} |> mapError { _ -> InstallStickerSetError in } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift index c064783ab5..4159f4464a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift @@ -1,5 +1,6 @@ import SwiftSignalKit import Postbox +import TelegramApi public extension TelegramEngine { final class Stickers { @@ -45,7 +46,7 @@ public extension TelegramEngine { return _internal_searchGifs(account: self.account, query: query, nextOffset: nextOffset) } - public func addStickerPackInteractively(info: StickerPackCollectionInfo, items: [ItemCollectionItem], positionInList: Int? = nil) -> Signal { + public func addStickerPackInteractively(info: StickerPackCollectionInfo, items: [StickerPackItem], positionInList: Int? = nil) -> Signal { return _internal_addStickerPackInteractively(postbox: self.account.postbox, info: info, items: items, positionInList: positionInList) } @@ -132,6 +133,13 @@ public extension TelegramEngine { |> ignoreValues } + public func clearRecentlyUsedEmoji() -> Signal { + return self.account.postbox.transaction { transaction -> Void in + _internal_clearRecentlyUsedEmoji(transaction: transaction) + } + |> ignoreValues + } + public func reorderStickerPacks(namespace: ItemCollectionId.Namespace, itemIds: [ItemCollectionId]) -> Signal { return self.account.postbox.transaction { transaction -> Void in let infos = transaction.getItemCollectionsInfos(namespace: namespace) @@ -155,5 +163,50 @@ public extension TelegramEngine { } |> ignoreValues } + + public func resolveInlineStickers(fileIds: [Int64]) -> Signal<[Int64: TelegramMediaFile], NoError> { + return self.account.postbox.transaction { transaction -> [Int64: TelegramMediaFile] in + var cachedFiles: [Int64: TelegramMediaFile] = [:] + for fileId in fileIds { + if let file = transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile { + cachedFiles[fileId] = file + } + } + return cachedFiles + } + |> mapToSignal { cachedFiles -> Signal<[Int64: TelegramMediaFile], NoError> in + if cachedFiles.count == fileIds.count { + return .single(cachedFiles) + } + + var unknownIds = Set() + for fileId in fileIds { + if cachedFiles[fileId] == nil { + unknownIds.insert(fileId) + } + } + + return self.account.network.request(Api.functions.messages.getCustomEmojiDocuments(documentId: Array(unknownIds))) + |> map(Optional.init) + |> `catch` { _ -> Signal<[Api.Document]?, NoError> in + return .single(nil) + } + |> mapToSignal { result -> Signal<[Int64: TelegramMediaFile], NoError> in + guard let result = result else { + return .single(cachedFiles) + } + return self.account.postbox.transaction { transaction -> [Int64: TelegramMediaFile] in + var resultFiles: [Int64: TelegramMediaFile] = cachedFiles + for document in result { + if let file = telegramMediaFileFromApiDocument(document) { + resultFiles[file.fileId.id] = file + transaction.storeMediaIfNotPresent(media: file) + } + } + return resultFiles + } + } + } + } } } diff --git a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift index 6a13ab787c..85b40fb025 100644 --- a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift @@ -209,7 +209,7 @@ func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Mes let second = UInt32(hashValue & 0xffffffff) let stableId = first &+ second - return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) } public extension Message { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 1257695a51..13ae1184ec 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -529,7 +529,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati reactionActiveBackground: UIColor(rgb: 0xffffff, alpha: 1.0), reactionActiveForeground: .clear ) - ), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0x313131).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.05), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff) + ), primaryTextColor: UIColor(rgb: 0xffffff), secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), linkTextColor: UIColor(rgb: 0xffffff), linkHighlightColor: UIColor(rgb: 0xffffff, alpha: 0.5), scamColor: UIColor(rgb: 0xeb5545), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: UIColor(rgb: 0xffffff), accentControlColor: UIColor(rgb: 0xffffff), accentControlDisabledColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaActiveControlColor: UIColor(rgb: 0xffffff), mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: UIColor(rgb: 0x313131), pendingActivityColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileTitleColor: UIColor(rgb: 0xffffff), fileDescriptionColor: UIColor(rgb: 0xffffff, alpha: 0.5), fileDurationColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaPlaceholderColor: UIColor(rgb: 0xffffff, alpha: 0.2), polls: PresentationThemeChatBubblePolls(radioButton: UIColor(rgb: 0xffffff), radioProgress: UIColor(rgb: 0xffffff), highlight: UIColor(rgb: 0xffffff).withAlphaComponent(0.12), separator: UIColor(rgb: 0xffffff, alpha: 0.5), bar: UIColor(rgb: 0xffffff), barIconForeground: .clear, barPositive: UIColor(rgb: 0xffffff), barNegative: UIColor(rgb: 0xffffff)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0x000000, alpha: 0.5), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2, alpha: 0.18)), actionButtonsTextColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xffffff)), textSelectionColor: UIColor(rgb: 0xffffff, alpha: 0.2), textSelectionKnobColor: UIColor(rgb: 0xffffff) ), freeform: PresentationThemeBubbleColor( withWallpaper: PresentationThemeBubbleColorComponents( @@ -608,13 +608,16 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati panelSeparatorColor: UIColor(rgb: 0x3d3d40), panelIconColor: UIColor(rgb: 0x808080), panelHighlightedIconBackgroundColor: UIColor(rgb: 0x262628), + panelHighlightedIconColor: UIColor(rgb: 0x808080).mixedWith(UIColor(rgb: 0xffffff), alpha: 0.35), + panelContentVibrantOverlayColor: UIColor(rgb: 0x808080), stickersBackgroundColor: UIColor(rgb: 0x000000), stickersSectionTextColor: UIColor(rgb: 0x7b7b7b), stickersSearchBackgroundColor: UIColor(rgb: 0x1c1c1d), stickersSearchPlaceholderColor: UIColor(rgb: 0x8d8e93), stickersSearchPrimaryColor: UIColor(rgb: 0xffffff), stickersSearchControlColor: UIColor(rgb: 0x8d8e93), - gifsBackgroundColor: UIColor(rgb: 0x000000) + gifsBackgroundColor: UIColor(rgb: 0x000000), + backgroundColor: UIColor(rgb: 0x000000, alpha: 0.75) ) let inputButtonPanel = PresentationThemeInputButtonPanel( diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift index b351d10941..bf45c93fd5 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkTintedPresentationTheme.swift @@ -440,12 +440,15 @@ public func customizeDefaultDarkTintedPresentationTheme(theme: PresentationTheme panelSeparatorColor: mainBackgroundColor, panelIconColor: mainSecondaryTextColor?.withAlphaComponent(0.5), panelHighlightedIconBackgroundColor: inputBackgroundColor, + panelHighlightedIconColor: mainSecondaryTextColor?.withAlphaComponent(0.5).mixedWith(chat.inputPanel.primaryTextColor, alpha: 0.35), + panelContentVibrantOverlayColor: mainSecondaryTextColor?.withAlphaComponent(0.5), stickersBackgroundColor: additionalBackgroundColor, stickersSectionTextColor: mainSecondaryTextColor?.withAlphaComponent(0.5), stickersSearchBackgroundColor: accentColor?.withMultiplied(hue: 1.009, saturation: 0.621, brightness: 0.15), stickersSearchPlaceholderColor: accentColor?.withMultiplied(hue: 0.99, saturation: 0.243, brightness: 0.59), stickersSearchControlColor: accentColor?.withMultiplied(hue: 0.99, saturation: 0.243, brightness: 0.59), - gifsBackgroundColor: additionalBackgroundColor + gifsBackgroundColor: additionalBackgroundColor, + backgroundColor: additionalBackgroundColor?.withMultipliedAlpha(0.75) ), inputButtonPanel: chat.inputButtonPanel.withUpdated( panelSeparatorColor: mainBackgroundColor, @@ -837,13 +840,16 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres panelSeparatorColor: mainBackgroundColor, panelIconColor: mainSecondaryTextColor.withAlphaComponent(0.5), panelHighlightedIconBackgroundColor: inputBackgroundColor, + panelHighlightedIconColor: mainSecondaryTextColor.withAlphaComponent(0.5).mixedWith(inputPanel.primaryTextColor, alpha: 0.35), + panelContentVibrantOverlayColor: mainSecondaryTextColor.withAlphaComponent(0.5), stickersBackgroundColor: additionalBackgroundColor, stickersSectionTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), stickersSearchBackgroundColor: accentColor.withMultiplied(hue: 1.009, saturation: 0.621, brightness: 0.15), stickersSearchPlaceholderColor: accentColor.withMultiplied(hue: 0.99, saturation: 0.243, brightness: 0.59), stickersSearchPrimaryColor: .white, stickersSearchControlColor: accentColor.withMultiplied(hue: 0.99, saturation: 0.243, brightness: 0.59), - gifsBackgroundColor: additionalBackgroundColor + gifsBackgroundColor: additionalBackgroundColor, + backgroundColor: additionalBackgroundColor.withMultipliedAlpha(0.75) ) let inputButtonPanel = PresentationThemeInputButtonPanel( diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 0a9c295e36..703c677673 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -849,7 +849,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio inputStrokeColor: UIColor(rgb: 0x000000, alpha: 0.1), inputPlaceholderColor: UIColor(rgb: 0xbebec0), inputTextColor: UIColor(rgb: 0x000000), - inputControlColor: UIColor(rgb: 0xa0a7b0), + inputControlColor: UIColor(rgb: 0x868D98), actionControlFillColor: defaultDayAccentColor, actionControlForegroundColor: UIColor(rgb: 0xffffff), primaryTextColor: UIColor(rgb: 0x000000), @@ -862,13 +862,16 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio panelSeparatorColor: UIColor(rgb: 0xbec2c6), panelIconColor: UIColor(rgb: 0x858e99), panelHighlightedIconBackgroundColor: UIColor(rgb: 0x858e99, alpha: 0.2), + panelHighlightedIconColor: UIColor(rgb: 0x4D5561), + panelContentVibrantOverlayColor: day ? UIColor(white: 0.0, alpha: 0.3) : UIColor(white: 0.65, alpha: 0.65), stickersBackgroundColor: UIColor(rgb: 0xe8ebf0), stickersSectionTextColor: UIColor(rgb: 0x9099a2), stickersSearchBackgroundColor: UIColor(rgb: 0xd9dbe1), stickersSearchPlaceholderColor: UIColor(rgb: 0x8e8e93), stickersSearchPrimaryColor: UIColor(rgb: 0x000000), stickersSearchControlColor: UIColor(rgb: 0x8e8e93), - gifsBackgroundColor: UIColor(rgb: 0xffffff) + gifsBackgroundColor: UIColor(rgb: 0xffffff), + backgroundColor: UIColor(rgb: 0xffffff, alpha: 0.7) ) let inputButtonPanel = PresentationThemeInputButtonPanel( diff --git a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift index cbe4d11d2c..d04a40c8e7 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationTheme.swift @@ -1142,6 +1142,8 @@ public final class PresentationThemeInputMediaPanel { public let panelSeparatorColor: UIColor public let panelIconColor: UIColor public let panelHighlightedIconBackgroundColor: UIColor + public let panelHighlightedIconColor: UIColor + public let panelContentVibrantOverlayColor: UIColor public let stickersBackgroundColor: UIColor public let stickersSectionTextColor: UIColor public let stickersSearchBackgroundColor: UIColor @@ -1149,11 +1151,14 @@ public final class PresentationThemeInputMediaPanel { public let stickersSearchPrimaryColor: UIColor public let stickersSearchControlColor: UIColor public let gifsBackgroundColor: UIColor + public let backgroundColor: UIColor - public init(panelSeparatorColor: UIColor, panelIconColor: UIColor, panelHighlightedIconBackgroundColor: UIColor, stickersBackgroundColor: UIColor, stickersSectionTextColor: UIColor, stickersSearchBackgroundColor: UIColor, stickersSearchPlaceholderColor: UIColor, stickersSearchPrimaryColor: UIColor, stickersSearchControlColor: UIColor, gifsBackgroundColor: UIColor) { + public init(panelSeparatorColor: UIColor, panelIconColor: UIColor, panelHighlightedIconBackgroundColor: UIColor, panelHighlightedIconColor: UIColor, panelContentVibrantOverlayColor: UIColor, stickersBackgroundColor: UIColor, stickersSectionTextColor: UIColor, stickersSearchBackgroundColor: UIColor, stickersSearchPlaceholderColor: UIColor, stickersSearchPrimaryColor: UIColor, stickersSearchControlColor: UIColor, gifsBackgroundColor: UIColor, backgroundColor: UIColor) { self.panelSeparatorColor = panelSeparatorColor self.panelIconColor = panelIconColor self.panelHighlightedIconBackgroundColor = panelHighlightedIconBackgroundColor + self.panelHighlightedIconColor = panelHighlightedIconColor + self.panelContentVibrantOverlayColor = panelContentVibrantOverlayColor self.stickersBackgroundColor = stickersBackgroundColor self.stickersSectionTextColor = stickersSectionTextColor self.stickersSearchBackgroundColor = stickersSearchBackgroundColor @@ -1161,10 +1166,11 @@ public final class PresentationThemeInputMediaPanel { self.stickersSearchPrimaryColor = stickersSearchPrimaryColor self.stickersSearchControlColor = stickersSearchControlColor self.gifsBackgroundColor = gifsBackgroundColor + self.backgroundColor = backgroundColor } - public func withUpdated(panelSeparatorColor: UIColor? = nil, panelIconColor: UIColor? = nil, panelHighlightedIconBackgroundColor: UIColor? = nil, stickersBackgroundColor: UIColor? = nil, stickersSectionTextColor: UIColor? = nil, stickersSearchBackgroundColor: UIColor? = nil, stickersSearchPlaceholderColor: UIColor? = nil, stickersSearchPrimaryColor: UIColor? = nil, stickersSearchControlColor: UIColor? = nil, gifsBackgroundColor: UIColor? = nil) -> PresentationThemeInputMediaPanel { - return PresentationThemeInputMediaPanel(panelSeparatorColor: panelSeparatorColor ?? self.panelSeparatorColor, panelIconColor: panelIconColor ?? self.panelIconColor, panelHighlightedIconBackgroundColor: panelHighlightedIconBackgroundColor ?? self.panelHighlightedIconBackgroundColor, stickersBackgroundColor: stickersBackgroundColor ?? self.stickersBackgroundColor, stickersSectionTextColor: stickersSectionTextColor ?? self.stickersSectionTextColor, stickersSearchBackgroundColor: stickersSearchBackgroundColor ?? self.stickersSearchBackgroundColor, stickersSearchPlaceholderColor: stickersSearchPlaceholderColor ?? self.stickersSearchPlaceholderColor, stickersSearchPrimaryColor: stickersSearchPrimaryColor ?? self.stickersSearchPrimaryColor, stickersSearchControlColor: stickersSearchControlColor ?? self.stickersSearchControlColor, gifsBackgroundColor: gifsBackgroundColor ?? self.gifsBackgroundColor) + public func withUpdated(panelSeparatorColor: UIColor? = nil, panelIconColor: UIColor? = nil, panelHighlightedIconBackgroundColor: UIColor? = nil, panelHighlightedIconColor: UIColor? = nil, panelContentVibrantOverlayColor: UIColor? = nil, stickersBackgroundColor: UIColor? = nil, stickersSectionTextColor: UIColor? = nil, stickersSearchBackgroundColor: UIColor? = nil, stickersSearchPlaceholderColor: UIColor? = nil, stickersSearchPrimaryColor: UIColor? = nil, stickersSearchControlColor: UIColor? = nil, gifsBackgroundColor: UIColor? = nil, backgroundColor: UIColor? = nil) -> PresentationThemeInputMediaPanel { + return PresentationThemeInputMediaPanel(panelSeparatorColor: panelSeparatorColor ?? self.panelSeparatorColor, panelIconColor: panelIconColor ?? self.panelIconColor, panelHighlightedIconBackgroundColor: panelHighlightedIconBackgroundColor ?? self.panelHighlightedIconBackgroundColor, panelHighlightedIconColor: panelHighlightedIconColor ?? self.panelHighlightedIconColor, panelContentVibrantOverlayColor: panelContentVibrantOverlayColor ?? self.panelContentVibrantOverlayColor, stickersBackgroundColor: stickersBackgroundColor ?? self.stickersBackgroundColor, stickersSectionTextColor: stickersSectionTextColor ?? self.stickersSectionTextColor, stickersSearchBackgroundColor: stickersSearchBackgroundColor ?? self.stickersSearchBackgroundColor, stickersSearchPlaceholderColor: stickersSearchPlaceholderColor ?? self.stickersSearchPlaceholderColor, stickersSearchPrimaryColor: stickersSearchPrimaryColor ?? self.stickersSearchPrimaryColor, stickersSearchControlColor: stickersSearchControlColor ?? self.stickersSearchControlColor, gifsBackgroundColor: gifsBackgroundColor ?? self.gifsBackgroundColor, backgroundColor: backgroundColor ?? self.backgroundColor) } } diff --git a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift index b302e7529f..d04b76ed88 100644 --- a/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift +++ b/submodules/TelegramPresentationData/Sources/PresentationThemeCodable.swift @@ -1605,6 +1605,8 @@ extension PresentationThemeInputMediaPanel: Codable { case panelSeparator case panelIcon case panelHighlightedIconBg + case panelHighlightedIcon + case panelContentVibrantOverlay case stickersBg case stickersSectionText case stickersSearchBg @@ -1612,20 +1614,43 @@ extension PresentationThemeInputMediaPanel: Codable { case stickersSearchPrimary case stickersSearchControl case gifsBg + case bg } public convenience init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) + + let backgroundColor: UIColor + if let value = try? decodeColor(values, .bg) { + backgroundColor = value + } else { + backgroundColor = try decodeColor(values, .gifsBg).withMultipliedAlpha(0.75) + } + + let panelHighlightedIconColor: UIColor + if let value = try? decodeColor(values, .panelHighlightedIcon) { + panelHighlightedIconColor = value + } else if let value = try? decodeColor(values, .panelHighlightedIcon, fallbackKey: "chat.inputPanel.inputText") { + let defaultColor = try decodeColor(values, .panelIcon) + panelHighlightedIconColor = defaultColor.mixedWith(value, alpha: 0.35) + } else { + panelHighlightedIconColor = try decodeColor(values, .panelIcon) + } + + let codingPath = decoder.codingPath.map { $0.stringValue }.joined(separator: ".") + self.init(panelSeparatorColor: try decodeColor(values, .panelSeparator), panelIconColor: try decodeColor(values, .panelIcon), panelHighlightedIconBackgroundColor: try decodeColor(values, .panelHighlightedIconBg), + panelHighlightedIconColor: panelHighlightedIconColor, + panelContentVibrantOverlayColor: try decodeColor(values, .panelContentVibrantOverlay, fallbackKey: "\(codingPath).panelIcon"), stickersBackgroundColor: try decodeColor(values, .stickersBg), stickersSectionTextColor: try decodeColor(values, .stickersSectionText), stickersSearchBackgroundColor: try decodeColor(values, .stickersSearchBg), stickersSearchPlaceholderColor: try decodeColor(values, .stickersSearchPlaceholder), stickersSearchPrimaryColor: try decodeColor(values, .stickersSearchPrimary), stickersSearchControlColor: try decodeColor(values, .stickersSearchControl), - gifsBackgroundColor: try decodeColor(values, .gifsBg)) + gifsBackgroundColor: try decodeColor(values, .gifsBg), backgroundColor: backgroundColor) } public func encode(to encoder: Encoder) throws { @@ -1633,6 +1658,8 @@ extension PresentationThemeInputMediaPanel: Codable { try encodeColor(&values, self.panelSeparatorColor, .panelSeparator) try encodeColor(&values, self.panelIconColor, .panelIcon) try encodeColor(&values, self.panelHighlightedIconBackgroundColor, .panelHighlightedIconBg) + try encodeColor(&values, self.panelHighlightedIconColor, .panelHighlightedIcon) + try encodeColor(&values, self.panelContentVibrantOverlayColor, .panelContentVibrantOverlay) try encodeColor(&values, self.stickersBackgroundColor, .stickersBg) try encodeColor(&values, self.stickersSectionTextColor, .stickersSectionText) try encodeColor(&values, self.stickersSearchBackgroundColor, .stickersSearchBg) @@ -1640,6 +1667,7 @@ extension PresentationThemeInputMediaPanel: Codable { try encodeColor(&values, self.stickersSearchPrimaryColor, .stickersSearchPrimary) try encodeColor(&values, self.stickersSearchControlColor, .stickersSearchControl) try encodeColor(&values, self.gifsBackgroundColor, .gifsBg) + try encodeColor(&values, self.backgroundColor, .bg) } } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index da1c28b02e..38bc5537d3 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -312,4 +312,7 @@ public enum PresentationResourceParameterKey: Hashable { case chatMessageCommentsArrowIcon(incoming: Bool) case chatMessageCommentsUnreadDotIcon(incoming: Bool) case chatMessageRepliesIcon(incoming: Bool) + + case chatEntityKeyboardLock(color: UInt32) + case chatInputMediaPanelGridDismissImage(color: UInt32) } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index e569f326f5..b3e6d7d8da 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -371,9 +371,9 @@ public struct PresentationResourcesChat { }) } - public static func chatInputMediaPanelGridDismissImage(_ theme: PresentationTheme) -> UIImage? { - return theme.image(PresentationResourceKey.chatInputMediaPanelGridDismissImage.rawValue, { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/GridDismissIcon"), color: theme.chat.inputMediaPanel.panelIconColor.withAlphaComponent(0.65)) + public static func chatInputMediaPanelGridDismissImage(_ theme: PresentationTheme, color: UIColor) -> UIImage? { + return theme.image(PresentationResourceParameterKey.chatInputMediaPanelGridDismissImage(color: color.argb), { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/GridDismissIcon"), color: color) }) } @@ -1281,4 +1281,10 @@ public struct PresentationResourcesChat { return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BotWebApp"), color: theme.chat.inputButtonPanel.buttonTextColor) }) } + + public static func chatEntityKeyboardLock(_ theme: PresentationTheme, color: UIColor) -> UIImage? { + return theme.image(PresentationResourceParameterKey.chatEntityKeyboardLock(color: color.argb), { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelSectionLockIcon"), color: color) + }) + } } diff --git a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index cc00c25f01..74664be74d 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -1,8 +1,10 @@ import Foundation +import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences import PlatformRestrictionMatching +import TextFormat public enum MessageContentKindKey { case text @@ -26,7 +28,7 @@ public enum MessageContentKindKey { } public enum MessageContentKind: Equatable { - case text(String) + case text(NSAttributedString) case image case video case videoMessage @@ -87,6 +89,40 @@ public enum MessageContentKind: Equatable { } } +public func messageTextWithAttributes(message: EngineMessage) -> NSAttributedString { + var attributedText = NSAttributedString(string: message.text) + + var entities: TextEntitiesMessageAttribute? + for attribute in message.attributes { + if let attribute = attribute as? TextEntitiesMessageAttribute { + entities = attribute + break + } + } + if let entities = entities?.entities { + let updatedString = NSMutableAttributedString(attributedString: attributedText) + + for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) { + guard case let .CustomEmoji(stickerPack, fileId) = entity.type else { + continue + } + + let range = NSRange(location: entity.range.lowerBound, length: entity.range.upperBound - entity.range.lowerBound) + + let currentDict = updatedString.attributes(at: range.lowerBound, effectiveRange: nil) + var updatedAttributes: [NSAttributedString.Key: Any] = currentDict + //updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) + + let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) + updatedString.replaceCharacters(in: range, with: insertString) + } + attributedText = updatedString + } + + return attributedText +} + public func messageContentKind(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> MessageContentKind { for attribute in message.attributes { if let attribute = attribute as? RestrictedContentMessageAttribute { @@ -101,7 +137,7 @@ public func messageContentKind(contentSettings: ContentSettings, message: Engine return kind } } - return .text(message.text) + return .text(messageTextWithAttributes(message: message)) } public func mediaContentKind(_ media: EngineMedia, message: EngineMessage? = nil, strings: PresentationStrings? = nil, nameDisplayOrder: PresentationPersonNameOrder? = nil, dateTimeFormat: PresentationDateTimeFormat? = nil, accountPeerId: EnginePeer.Id? = nil) -> MessageContentKind? { @@ -170,7 +206,7 @@ public func mediaContentKind(_ media: EngineMedia, message: EngineMessage? = nil } case .action: if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId { - return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat ?? PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), message: message, accountPeerId: accountPeerId, forChatList: false)?.0 ?? "") + return .text(NSAttributedString(string: plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat ?? PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), message: message, accountPeerId: accountPeerId, forChatList: false)?.0 ?? "")) } else { return nil } @@ -189,59 +225,59 @@ public func mediaContentKind(_ media: EngineMedia, message: EngineMessage? = nil } } -public func stringForMediaKind(_ kind: MessageContentKind, strings: PresentationStrings) -> (String, Bool) { +public func stringForMediaKind(_ kind: MessageContentKind, strings: PresentationStrings) -> (NSAttributedString, Bool) { switch kind { case let .text(text): return (foldLineBreaks(text), false) case .image: - return (strings.Message_Photo, true) + return (NSAttributedString(string: strings.Message_Photo), true) case .video: - return (strings.Message_Video, true) + return (NSAttributedString(string: strings.Message_Video), true) case .videoMessage: - return (strings.Message_VideoMessage, true) + return (NSAttributedString(string: strings.Message_VideoMessage), true) case .audioMessage: - return (strings.Message_Audio, true) + return (NSAttributedString(string: strings.Message_Audio), true) case let .sticker(text): if text.isEmpty { - return (strings.Message_Sticker, true) + return (NSAttributedString(string: strings.Message_Sticker), true) } else { - return (strings.Message_StickerText(text).string, true) + return (NSAttributedString(string: strings.Message_StickerText(text).string), true) } case .animation: - return (strings.Message_Animation, true) + return (NSAttributedString(string: strings.Message_Animation), true) case let .file(text): if text.isEmpty { - return (strings.Message_File, true) + return (NSAttributedString(string: strings.Message_File), true) } else { - return (text, true) + return (NSAttributedString(string: text), true) } case .contact: - return (strings.Message_Contact, true) + return (NSAttributedString(string: strings.Message_Contact), true) case let .game(text): - return (text, true) + return (NSAttributedString(string: text), true) case .location: - return (strings.Message_Location, true) + return (NSAttributedString(string: strings.Message_Location), true) case .liveLocation: - return (strings.Message_LiveLocation, true) + return (NSAttributedString(string: strings.Message_LiveLocation), true) case .expiredImage: - return (strings.Message_ImageExpired, true) + return (NSAttributedString(string: strings.Message_ImageExpired), true) case .expiredVideo: - return (strings.Message_VideoExpired, true) + return (NSAttributedString(string: strings.Message_VideoExpired), true) case let .poll(text): - return ("📊 \(text)", false) + return (NSAttributedString(string: "📊 \(text)"), false) case let .restricted(text): - return (text, false) + return (NSAttributedString(string: text), false) case let .dice(emoji): - return (emoji, true) + return (NSAttributedString(string: emoji), true) case let .invoice(text): - return (text, true) + return (NSAttributedString(string: text), true) } } -public func descriptionStringForMessage(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> (String, Bool, Bool) { +public func descriptionStringForMessage(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> (NSAttributedString, Bool, Bool) { let contentKind = messageContentKind(contentSettings: contentSettings, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId) if !message.text.isEmpty && ![.expiredImage, .expiredVideo].contains(contentKind.key) { - return (foldLineBreaks(message.text), false, true) + return (foldLineBreaks(messageTextWithAttributes(message: message)), false, true) } let result = stringForMediaKind(contentKind, strings: strings) return (result.0, result.1, false) @@ -263,6 +299,49 @@ public func foldLineBreaks(_ text: String) -> String { return result } +public func foldLineBreaks(_ text: NSAttributedString) -> NSAttributedString { + let remainingString = NSMutableAttributedString(attributedString: text) + var lines: [NSAttributedString] = [] + while true { + if let range = remainingString.string.range(of: "\n") { + let mappedRange = NSRange(range, in: remainingString.string) + lines.append(remainingString.attributedSubstring(from: NSRange(location: 0, length: mappedRange.upperBound))) + remainingString.replaceCharacters(in: NSRange(location: 0, length: mappedRange.upperBound), with: "") + } else { + if lines.isEmpty { + return text + } + if !remainingString.string.isEmpty { + lines.append(remainingString) + } + break + } + } + + let result = NSMutableAttributedString() + + for line in lines { + if line.string.isEmpty { + continue + } + if result.string.isEmpty { + result.append(line) + } else { + let currentAttributes = line.attributes(at: 0, effectiveRange: nil).filter { key, _ in + switch key { + case .font, .foregroundColor: + return true + default: + return false + } + } + result.append(NSAttributedString(string: " ", attributes: currentAttributes)) + result.append(line) + } + } + + return result +} public func trimToLineCount(_ text: String, lineCount: Int) -> String { if lineCount < 1 { diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 6297ea853e..22e99077a1 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -1,5 +1,6 @@ import Foundation import UIKit +import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -15,6 +16,10 @@ private func spoilerAttributes(primaryTextColor: UIColor) -> MarkdownAttributeSe return MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.Spoiler: true]) } +private func customEmojiAttributes(primaryTextColor: UIColor, emoji: ChatTextInputTextCustomEmojiAttribute) -> MarkdownAttributeSet { + return MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: emoji]) +} + private func peerMentionAttributes(primaryTextColor: UIColor, peerId: EnginePeer.Id) -> MarkdownAttributeSet { return MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.PeerMention: TelegramPeerMention(peerId: peerId, mention: "")]) } @@ -29,15 +34,18 @@ private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, E return result } -public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> (String, [NSRange])? { +public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> (text: String, spoilerRanges: [NSRange], customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)])? { if let attributedString = universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: forChatList) { var ranges: [NSRange] = [] + var customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)] = [] attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: [], using: { attributes, range, _ in if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)] { ranges.append(range) + } else if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + customEmojiRanges.append((range, value)) } }) - return (attributedString.string, ranges) + return (attributedString.string, ranges, customEmojiRanges) } else { return nil } @@ -176,9 +184,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, var type: PinnnedMediaType if let pinnedMessage = pinnedMessage?._asMessage() { let entities = (pinnedMessage.textEntitiesAttribute?.entities ?? []).filter { entity in - if case .Spoiler = entity.type { + switch entity.type { + case .Spoiler, .CustomEmoji: return true - } else { + default: return false } } @@ -264,9 +273,18 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, let location = entityOffset + entity.range.startIndex let length = max(0, min(entity.range.count, stringLength - location - 1)) if length > 0 { - let index = ranges.count - ranges.append((ranges.count, NSRange(location: location, length: length))) - attributes[index] = spoilerAttributes(primaryTextColor: primaryTextColor) + switch entity.type { + case .Spoiler: + let index = ranges.count + ranges.append((ranges.count, NSRange(location: location, length: length))) + attributes[index] = spoilerAttributes(primaryTextColor: primaryTextColor) + case let .CustomEmoji(stickerPack, fileId): + let index = ranges.count + ranges.append((ranges.count, NSRange(location: location, length: length))) + attributes[index] = customEmojiAttributes(primaryTextColor: primaryTextColor, emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile)) + default: + break + } } } attributedString = addAttributesToStringWithRanges((string, ranges), body: bodyAttributes, argumentAttributes: attributes) @@ -567,7 +585,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } } case let .customText(text, entities): - 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) + 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()) case let .botDomainAccessGranted(domain): attributedString = NSAttributedString(string: strings.AuthSessions_Message(domain).string, font: titleFont, textColor: primaryTextColor) case let .botSentSecureValues(types): @@ -652,6 +670,15 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } case let .webViewData(text): attributedString = NSAttributedString(string: strings.Notification_WebAppSentData(text).string, font: titleFont, textColor: primaryTextColor) + case let .giftPremium(currency, amount, _): + let price = formatCurrencyAmount(amount, currency: currency) + if message.author?.id == accountPeerId { + attributedString = addAttributesToStringWithRanges(strings.Notification_PremiumGift_SentYou(price)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes]) + } else { + var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]) + attributes[1] = boldAttributes + attributedString = addAttributesToStringWithRanges(strings.Notification_PremiumGift_Sent(authorName, price)._tuple, body: bodyAttributes, argumentAttributes: attributes) + } case .unknown: attributedString = nil } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 22e7126343..4d9a0a1245 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -282,12 +282,18 @@ swift_library( "//submodules/TelegramUI/Components/AudioWaveformComponent:AudioWaveformComponent", "//submodules/TelegramUI/Components/EditableChatTextNode:EditableChatTextNode", "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", - "//submodules/TelegramUI/Components/EmojiKeyboard:EmojiKeyboard", + "//submodules/TelegramUI/Components/EntityKeyboard:EntityKeyboard", "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", "//submodules/TelegramUI/Components/LottieAnimationCache:LottieAnimationCache", + "//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/TelegramUI/Components/ChatInputPanelContainer:ChatInputPanelContainer", + "//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", "//submodules/Media/ConvertOpusToAAC:ConvertOpusToAAC", "//submodules/Media/LocalAudioTranscription:LocalAudioTranscription", + "//submodules/Components/PagerComponent:PagerComponent", + "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", ] + select({ "@build_bazel_rules_apple//apple:ios_armv7": [], "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, diff --git a/submodules/TelegramUI/Components/AnimationCache/BUILD b/submodules/TelegramUI/Components/AnimationCache/BUILD index c5773d4849..e655aa9fe6 100644 --- a/submodules/TelegramUI/Components/AnimationCache/BUILD +++ b/submodules/TelegramUI/Components/AnimationCache/BUILD @@ -13,6 +13,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/CryptoUtils:CryptoUtils", "//submodules/ManagedFile:ManagedFile", + "//submodules/TelegramUI/Components/AnimationCache/ImageDCT:ImageDCT", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD new file mode 100644 index 0000000000..030187e3e1 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD @@ -0,0 +1,26 @@ + +objc_library( + name = "ImageDCT", + enable_modules = True, + module_name = "ImageDCT", + srcs = glob([ + "Sources/**/*.m", + "Sources/**/*.mm", + "Sources/**/*.c", + "Sources/**/*.cpp", + "Sources/**/*.h", + ]), + hdrs = glob([ + "PublicHeaders/**/*.h", + ]), + includes = [ + "PublicHeaders", + ], + sdk_frameworks = [ + "Foundation", + "Accelerate", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h new file mode 100644 index 0000000000..236cdd2f9f --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h @@ -0,0 +1,26 @@ +#ifndef DctImageTransform_h +#define DctImageTransform_h + +#import + +#import + +@interface ImageDCTTable : NSObject + +- (instancetype _Nonnull)initWithQuality:(NSInteger)quality isChroma:(bool)isChroma; +- (instancetype _Nullable)initWithData:(NSData * _Nonnull)data; + +- (NSData * _Nonnull)serializedData; + +@end + +@interface ImageDCT : NSObject + +- (instancetype _Nonnull)initWithTable:(ImageDCTTable * _Nonnull)table; + +- (void)forwardWithPixels:(uint8_t const * _Nonnull)pixels coefficients:(int16_t * _Nonnull)coefficients width:(NSInteger)width height:(NSInteger)height bytesPerRow:(NSInteger)bytesPerRow __attribute__((objc_direct)); +- (void)inverseWithCoefficients:(int16_t const * _Nonnull)coefficients pixels:(uint8_t * _Nonnull)pixels width:(NSInteger)width height:(NSInteger)height coefficientsPerRow:(NSInteger)coefficientsPerRow bytesPerRow:(NSInteger)bytesPerRow __attribute__((objc_direct)); + +@end + +#endif /* DctImageTransform_h */ diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h new file mode 100644 index 0000000000..81a3ee6569 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h @@ -0,0 +1,10 @@ +#ifndef YuvConversion_h +#define YuvConversion_h + +#import + +void splitRGBAIntoYUVAPlanes(uint8_t const *argb, uint8_t *outY, uint8_t *outU, uint8_t *outV, uint8_t *outA, int width, int height, int bytesPerRow); +void combineYUVAPlanesIntoARBB(uint8_t *argb, uint8_t const *inY, uint8_t const *inU, uint8_t const *inV, uint8_t const *inA, int width, int height, int bytesPerRow); +void scaleImagePlane(uint8_t *outPlane, int outWidth, int outHeight, int outBytesPerRow, uint8_t const *inPlane, int inWidth, int inHeight, int inBytesPerRow); + +#endif /* YuvConversion_h */ diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp new file mode 100644 index 0000000000..fe67756534 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp @@ -0,0 +1,398 @@ +#import "DCT.h" + +#include "DCTCommon.h" + +#include + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ + +typedef unsigned short UDCTELEM; +typedef unsigned int UDCTELEM2; + +typedef long JLONG; + +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ + +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ + +#define CENTERJSAMPLE 128 + +namespace { + +int flss(uint16_t val) { + int bit; + + bit = 16; + + if (!val) + return 0; + + if (!(val & 0xff00)) { + bit -= 8; + val <<= 8; + } + if (!(val & 0xf000)) { + bit -= 4; + val <<= 4; + } + if (!(val & 0xc000)) { + bit -= 2; + val <<= 2; + } + if (!(val & 0x8000)) { + bit -= 1; + val <<= 1; + } + + return bit; +} + +int compute_reciprocal(uint16_t divisor, DCTELEM *dtbl) { + UDCTELEM2 fq, fr; + UDCTELEM c; + int b, r; + + if (divisor == 1) { + /* divisor == 1 means unquantized, so these reciprocal/correction/shift + * values will cause the C quantization algorithm to act like the + * identity function. Since only the C quantization algorithm is used in + * these cases, the scale value is irrelevant. + */ + dtbl[DCTSIZE2 * 0] = (DCTELEM)1; /* reciprocal */ + dtbl[DCTSIZE2 * 1] = (DCTELEM)0; /* correction */ + dtbl[DCTSIZE2 * 2] = (DCTELEM)1; /* scale */ + dtbl[DCTSIZE2 * 3] = -(DCTELEM)(sizeof(DCTELEM) * 8); /* shift */ + return 0; + } + + b = flss(divisor) - 1; + r = sizeof(DCTELEM) * 8 + b; + + fq = ((UDCTELEM2)1 << r) / divisor; + fr = ((UDCTELEM2)1 << r) % divisor; + + c = divisor / 2; /* for rounding */ + + if (fr == 0) { /* divisor is power of two */ + /* fq will be one bit too large to fit in DCTELEM, so adjust */ + fq >>= 1; + r--; + } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */ + c++; + } else { /* fractional part is > 0.5 */ + fq++; + } + + dtbl[DCTSIZE2 * 0] = (DCTELEM)fq; /* reciprocal */ + dtbl[DCTSIZE2 * 1] = (DCTELEM)c; /* correction + roundfactor */ +#ifdef WITH_SIMD + dtbl[DCTSIZE2 * 2] = (DCTELEM)(1 << (sizeof(DCTELEM) * 8 * 2 - r)); /* scale */ +#else + dtbl[DCTSIZE2 * 2] = 1; +#endif + dtbl[DCTSIZE2 * 3] = (DCTELEM)r - sizeof(DCTELEM) * 8; /* shift */ + + if (r <= 16) return 0; + else return 1; +} + +#define DESCALE(x, n) RIGHT_SHIFT(x, n) + + +/* Multiply a DCTELEM variable by an JLONG constant, and immediately + * descale to yield a DCTELEM result. + */ + +#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS)) +#define MULTIPLY16V16(var1, var2) ((var1) * (var2)) + +static DCTELEM std_luminance_quant_tbl[DCTSIZE2] = { + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; +static DCTELEM std_chrominance_quant_tbl[DCTSIZE2] = { + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +int jpeg_quality_scaling(int quality) +/* Convert a user-specified quality rating to a percentage scaling factor + * for an underlying quantization table, using our recommended scaling curve. + * The input 'quality' factor should be 0 (terrible) to 100 (very good). + */ +{ + /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ + if (quality <= 0) quality = 1; + if (quality > 100) quality = 100; + + /* The basic table is used as-is (scaling 100) for a quality of 50. + * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; + * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table + * to make all the table entries 1 (hence, minimum quantization loss). + * Qualities 1..50 are converted to scaling percentage 5000/Q. + */ + if (quality < 50) + quality = 5000 / quality; + else + quality = 200 - quality * 2; + + return quality; +} + +void jpeg_add_quant_table(DCTELEM *qtable, DCTELEM const *basicTable, int scale_factor, bool forceBaseline) +/* Define a quantization table equal to the basic_table times + * a scale factor (given as a percentage). + * If force_baseline is TRUE, the computed quantization table entries + * are limited to 1..255 for JPEG baseline compatibility. + */ +{ + int i; + long temp; + + for (i = 0; i < DCTSIZE2; i++) { + temp = ((long)basicTable[i] * scale_factor + 50L) / 100L; + /* limit the values to the valid range */ + if (temp <= 0L) temp = 1L; + if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ + if (forceBaseline && temp > 255L) + temp = 255L; /* limit to baseline range if requested */ + qtable[i] = (uint16_t)temp; + } +} + +void jpeg_set_quality(DCTELEM *qtable, DCTELEM const *basicTable, int quality) +/* Set or change the 'quality' (quantization) setting, using default tables. + * This is the standard quality-adjusting entry point for typical user + * interfaces; only those who want detailed control over quantization tables + * would use the preceding three routines directly. + */ +{ + /* Convert user 0-100 rating to percentage scaling */ + quality = jpeg_quality_scaling(quality); + + /* Set up standard quality tables */ + jpeg_add_quant_table(qtable, basicTable, quality, false); +} + +void getDivisors(DCTELEM *dtbl, DCTELEM const *qtable) { +#define CONST_BITS 14 +#define RIGHT_SHIFT(x, shft) ((x) >> (shft)) + + static const int16_t aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + + for (int i = 0; i < DCTSIZE2; i++) { + if (!compute_reciprocal( + DESCALE(MULTIPLY16V16((JLONG)qtable[i], + (JLONG)aanscales[i]), + CONST_BITS - 3), &dtbl[i])) { + } + } +} + +void quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) +{ + int i; + DCTELEM temp; + JCOEFPTR output_ptr = coef_block; + + UDCTELEM recip, corr; + int shift; + UDCTELEM2 product; + + for (i = 0; i < DCTSIZE2; i++) { + temp = workspace[i]; + recip = divisors[i + DCTSIZE2 * 0]; + corr = divisors[i + DCTSIZE2 * 1]; + shift = divisors[i + DCTSIZE2 * 3]; + + if (temp < 0) { + temp = -temp; + product = (UDCTELEM2)(temp + corr) * recip; + product >>= shift + sizeof(DCTELEM) * 8; + temp = (DCTELEM)product; + temp = -temp; + } else { + product = (UDCTELEM2)(temp + corr) * recip; + product >>= shift + sizeof(DCTELEM) * 8; + temp = (DCTELEM)product; + } + output_ptr[i] = (JCOEF)temp; + } +} + +void generateForwardDctData(DCTELEM const *qtable, std::vector &data) { + data.resize(DCTSIZE2 * 4 * sizeof(DCTELEM)); + getDivisors((DCTELEM *)data.data(), qtable); +} + +void generateInverseDctData(DCTELEM const *qtable, std::vector &data) { + data.resize(DCTSIZE2 * sizeof(IFAST_MULT_TYPE)); + IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)data.data(); + +#define CONST_BITS 14 + static const int16_t aanscales[DCTSIZE2] = { + /* precomputed values scaled up by 14 bits */ + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270, + 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906, + 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315, + 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, + 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552, + 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446, + 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247 + }; + + for (int i = 0; i < DCTSIZE2; i++) { + ifmtbl[i] = (IFAST_MULT_TYPE) + DESCALE(MULTIPLY16V16((JLONG)qtable[i], + (JLONG)aanscales[i]), + CONST_BITS - IFAST_SCALE_BITS); + } +} + +static const int zigZagInv[DCTSIZE2] = { + 0,1,8,16,9,2,3,10, + 17,24,32,25,18,11,4,5, + 12,19,26,33,40,48,41,34, + 27,20,13,6,7,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +static const int zigZag[DCTSIZE2] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + +void performForwardDct(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow, DCTELEM *divisors) { + DCTELEM block[DCTSIZE2]; + JCOEF coefBlock[DCTSIZE2]; + + for (int y = 0; y < height; y += DCTSIZE) { + for (int x = 0; x < width; x += DCTSIZE) { + for (int blockY = 0; blockY < DCTSIZE; blockY++) { + for (int blockX = 0; blockX < DCTSIZE; blockX++) { + block[blockY * DCTSIZE + blockX] = ((DCTELEM)pixels[(y + blockY) * bytesPerRow + (x + blockX)]) - CENTERJSAMPLE; + } + } + + dct_jpeg_fdct_ifast(block); + + quantize(coefBlock, divisors, block); + + for (int blockY = 0; blockY < DCTSIZE; blockY++) { + for (int blockX = 0; blockX < DCTSIZE; blockX++) { + coefficients[(y + blockY) * bytesPerRow + (x + blockX)] = coefBlock[zigZagInv[blockY * DCTSIZE + blockX]]; + } + } + } + } +} + +void performInverseDct(int16_t const * coefficients, uint8_t *pixels, int width, int height, int coefficientsPerRow, int bytesPerRow, DctAuxiliaryData *auxiliaryData, IFAST_MULT_TYPE *ifmtbl) { + DCTELEM coefficientBlock[DCTSIZE2]; + JSAMPLE pixelBlock[DCTSIZE2]; + + for (int y = 0; y < height; y += DCTSIZE) { + for (int x = 0; x < width; x += DCTSIZE) { + for (int blockY = 0; blockY < DCTSIZE; blockY++) { + for (int blockX = 0; blockX < DCTSIZE; blockX++) { + coefficientBlock[zigZag[blockY * DCTSIZE + blockX]] = coefficients[(y + blockY) * coefficientsPerRow + (x + blockX)]; + } + } + + dct_jpeg_idct_ifast(auxiliaryData, ifmtbl, coefficientBlock, pixelBlock); + + for (int blockY = 0; blockY < DCTSIZE; blockY++) { + for (int blockX = 0; blockX < DCTSIZE; blockX++) { + pixels[(y + blockY) * bytesPerRow + (x + blockX)] = pixelBlock[blockY * DCTSIZE + blockX]; + } + } + } + } +} + +} + +namespace dct { + +DCTTable DCTTable::generate(int quality, bool isChroma) { + DCTTable result; + result.table.resize(DCTSIZE2); + + if (isChroma) { + jpeg_set_quality(result.table.data(), std_chrominance_quant_tbl, quality); + } else { + jpeg_set_quality(result.table.data(), std_luminance_quant_tbl, quality); + } + + return result; +} + +DCTTable DCTTable::initializeEmpty() { + DCTTable result; + result.table.resize(DCTSIZE2); + return result; +} + +class DCTInternal { +public: + DCTInternal(DCTTable const &dctTable) { + auxiliaryData = createDctAuxiliaryData(); + + generateForwardDctData(dctTable.table.data(), forwardDctData); + generateInverseDctData(dctTable.table.data(), inverseDctData); + } + + ~DCTInternal() { + freeDctAuxiliaryData(auxiliaryData); + } + +public: + struct DctAuxiliaryData *auxiliaryData = nullptr; + std::vector forwardDctData; + std::vector inverseDctData; +}; + +DCT::DCT(DCTTable const &dctTable) { + _internal = new DCTInternal(dctTable); +} + +DCT::~DCT() { + delete _internal; +} + +void DCT::forward(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow) { + performForwardDct(pixels, coefficients, width, height, bytesPerRow, (DCTELEM *)_internal->forwardDctData.data()); +} + +void DCT::inverse(int16_t const *coefficients, uint8_t *pixels, int width, int height, int coefficientsPerRow, int bytesPerRow) { + performInverseDct(coefficients, pixels, width, height, coefficientsPerRow, bytesPerRow, _internal->auxiliaryData, (IFAST_MULT_TYPE *)_internal->inverseDctData.data()); +} + +} diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h new file mode 100644 index 0000000000..67031caa80 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h @@ -0,0 +1,34 @@ +#ifndef DCT_H +#define DCT_H + +#include "DCTCommon.h" + +#include +#include + +namespace dct { + +class DCTInternal; + +struct DCTTable { + static DCTTable generate(int quality, bool isChroma); + static DCTTable initializeEmpty(); + + std::vector table; +}; + +class DCT { +public: + DCT(DCTTable const &dctTable); + ~DCT(); + + void forward(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow); + void inverse(int16_t const *coefficients, uint8_t *pixels, int width, int height, int coefficientsPerRow, int bytesPerRow); + +private: + DCTInternal *_internal; +}; + +} + +#endif diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCTCommon.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCTCommon.h new file mode 100644 index 0000000000..b57f76e8de --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCTCommon.h @@ -0,0 +1,27 @@ +#ifndef DCT_COMMON_H +#define DCT_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef short DCTELEM; + +typedef short JCOEF; +typedef JCOEF *JCOEFPTR; + +typedef unsigned char JSAMPLE; +typedef JSAMPLE *JSAMPROW; + +struct DctAuxiliaryData; +struct DctAuxiliaryData *createDctAuxiliaryData(); +void freeDctAuxiliaryData(struct DctAuxiliaryData *data); + +void dct_jpeg_idct_ifast(struct DctAuxiliaryData *auxiliaryData, void *dct_table, JCOEFPTR coef_block, JSAMPROW output_buf); +void dct_jpeg_fdct_ifast(DCTELEM *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_C.c b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_C.c new file mode 100644 index 0000000000..c0846b6856 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_C.c @@ -0,0 +1,399 @@ +#import "DCTCommon.h" + +#if !defined(__aarch64__) + +#include +#include + +typedef long JLONG; + +#define CONST_BITS 8 +#define PASS1_BITS 2 + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ + +#define FIX_0_382683433 ((JLONG)98) /* FIX(0.382683433) */ +#define FIX_0_541196100 ((JLONG)139) /* FIX(0.541196100) */ +#define FIX_0_707106781 ((JLONG)181) /* FIX(0.707106781) */ +#define FIX_1_306562965 ((JLONG)334) /* FIX(1.306562965) */ + +#define FIX_1_082392200 ((JLONG)277) /* FIX(1.082392200) */ +#define FIX_1_414213562 ((JLONG)362) /* FIX(1.414213562) */ +#define FIX_1_847759065 ((JLONG)473) /* FIX(1.847759065) */ +#define FIX_2_613125930 ((JLONG)669) /* FIX(2.613125930) */ + +#define RIGHT_SHIFT(x, shft) ((x) >> (shft)) +#define IRIGHT_SHIFT(x, shft) ((x) >> (shft)) +#define DESCALE(x, n) RIGHT_SHIFT(x, n) +#define IDESCALE(x, n) ((int)IRIGHT_SHIFT(x, n)) + +#define MULTIPLY(var, const) ((DCTELEM)DESCALE((var) * (const), CONST_BITS)) + +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ + +#define DEQUANTIZE(coef, quantval) (((IFAST_MULT_TYPE)(coef)) * (quantval)) + +#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) + +void dct_jpeg_fdct_ifast(DCTELEM *data) +{ + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z1, z2, z3, z4, z5, z11, z13; + DCTELEM *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) { + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE - 1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE * 0] + dataptr[DCTSIZE * 7]; + tmp7 = dataptr[DCTSIZE * 0] - dataptr[DCTSIZE * 7]; + tmp1 = dataptr[DCTSIZE * 1] + dataptr[DCTSIZE * 6]; + tmp6 = dataptr[DCTSIZE * 1] - dataptr[DCTSIZE * 6]; + tmp2 = dataptr[DCTSIZE * 2] + dataptr[DCTSIZE * 5]; + tmp5 = dataptr[DCTSIZE * 2] - dataptr[DCTSIZE * 5]; + tmp3 = dataptr[DCTSIZE * 3] + dataptr[DCTSIZE * 4]; + tmp4 = dataptr[DCTSIZE * 3] - dataptr[DCTSIZE * 4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE * 0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE * 4] = tmp10 - tmp11; + + z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */ + dataptr[DCTSIZE * 2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE * 6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */ + z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */ + z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */ + z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE * 5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE * 3] = z13 - z2; + dataptr[DCTSIZE * 1] = z11 + z4; + dataptr[DCTSIZE * 7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + +struct DctAuxiliaryData { + JSAMPLE *allocated_sample_range_limit; + JSAMPLE *sample_range_limit; +}; + +static void prepare_range_limit_table(struct DctAuxiliaryData *data) +/* Allocate and fill in the sample_range_limit table */ +{ + JSAMPLE *table; + int i; + + table = (JSAMPLE *)malloc((5 * (MAXJSAMPLE + 1) + CENTERJSAMPLE) * sizeof(JSAMPLE)); + data->allocated_sample_range_limit = table; + table += (MAXJSAMPLE + 1); /* allow negative subscripts of simple table */ + data->sample_range_limit = table; + /* First segment of "simple" table: limit[x] = 0 for x < 0 */ + memset(table - (MAXJSAMPLE + 1), 0, (MAXJSAMPLE + 1) * sizeof(JSAMPLE)); + /* Main part of "simple" table: limit[x] = x */ + for (i = 0; i <= MAXJSAMPLE; i++) + table[i] = (JSAMPLE)i; + table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ + /* End of simple table, rest of first half of post-IDCT table */ + for (i = CENTERJSAMPLE; i < 2 * (MAXJSAMPLE + 1); i++) + table[i] = MAXJSAMPLE; + /* Second half of post-IDCT table */ + memset(table + (2 * (MAXJSAMPLE + 1)), 0, + (2 * (MAXJSAMPLE + 1) - CENTERJSAMPLE) * sizeof(JSAMPLE)); + memcpy(table + (4 * (MAXJSAMPLE + 1) - CENTERJSAMPLE), + data->sample_range_limit, CENTERJSAMPLE * sizeof(JSAMPLE)); +} + +struct DctAuxiliaryData *createDctAuxiliaryData() { + struct DctAuxiliaryData *result = malloc(sizeof(struct DctAuxiliaryData)); + memset(result, 0, sizeof(struct DctAuxiliaryData)); + + prepare_range_limit_table(result); + + return result; +} + +void freeDctAuxiliaryData(struct DctAuxiliaryData *data) { + if (data) { + free(data->allocated_sample_range_limit); + free(data); + } +} + +void dct_jpeg_idct_ifast(struct DctAuxiliaryData *auxiliaryData, void *dct_table, JCOEFPTR coef_block, JSAMPROW output_buf) { + DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + DCTELEM tmp10, tmp11, tmp12, tmp13; + DCTELEM z5, z10, z11, z12, z13; + JCOEFPTR inptr; + IFAST_MULT_TYPE *quantptr; + int *wsptr; + JSAMPROW outptr; + JSAMPLE *range_limit = IDCT_range_limit(auxiliaryData); + int ctr; + int workspace[DCTSIZE2]; /* buffers data between passes */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = coef_block; + quantptr = dct_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE * 1] == 0 && inptr[DCTSIZE * 2] == 0 && + inptr[DCTSIZE * 3] == 0 && inptr[DCTSIZE * 4] == 0 && + inptr[DCTSIZE * 5] == 0 && inptr[DCTSIZE * 6] == 0 && + inptr[DCTSIZE * 7] == 0) { + /* AC terms all zero */ + int dcval = (int)DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]); + + wsptr[DCTSIZE * 0] = dcval; + wsptr[DCTSIZE * 1] = dcval; + wsptr[DCTSIZE * 2] = dcval; + wsptr[DCTSIZE * 3] = dcval; + wsptr[DCTSIZE * 4] = dcval; + wsptr[DCTSIZE * 5] = dcval; + wsptr[DCTSIZE * 6] = dcval; + wsptr[DCTSIZE * 7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE * 0], quantptr[DCTSIZE * 0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE * 2], quantptr[DCTSIZE * 2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE * 4], quantptr[DCTSIZE * 4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE * 6], quantptr[DCTSIZE * 6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE * 1], quantptr[DCTSIZE * 1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE * 3], quantptr[DCTSIZE * 3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE * 5], quantptr[DCTSIZE * 5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE * 7], quantptr[DCTSIZE * 7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE * 0] = (int)(tmp0 + tmp7); + wsptr[DCTSIZE * 7] = (int)(tmp0 - tmp7); + wsptr[DCTSIZE * 1] = (int)(tmp1 + tmp6); + wsptr[DCTSIZE * 6] = (int)(tmp1 - tmp6); + wsptr[DCTSIZE * 2] = (int)(tmp2 + tmp5); + wsptr[DCTSIZE * 5] = (int)(tmp2 - tmp5); + wsptr[DCTSIZE * 4] = (int)(tmp3 + tmp4); + wsptr[DCTSIZE * 3] = (int)(tmp3 - tmp4); + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3, */ + /* and also undo the PASS1_BITS scaling. */ + + wsptr = workspace; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + outptr = output_buf + ctr * DCTSIZE; + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * On machines with very fast multiplication, it's possible that the + * test takes more time than it's worth. In that case this section + * may be commented out. + */ + +#ifndef NO_ZERO_ROW_TEST + if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 && + wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) { + /* AC terms all zero */ + JSAMPLE dcval = + range_limit[IDESCALE(wsptr[0], PASS1_BITS + 3) & RANGE_MASK]; + + outptr[0] = dcval; + outptr[1] = dcval; + outptr[2] = dcval; + outptr[3] = dcval; + outptr[4] = dcval; + outptr[5] = dcval; + outptr[6] = dcval; + outptr[7] = dcval; + + wsptr += DCTSIZE; /* advance pointer to next row */ + continue; + } +#endif + + /* Even part */ + + tmp10 = ((DCTELEM)wsptr[0] + (DCTELEM)wsptr[4]); + tmp11 = ((DCTELEM)wsptr[0] - (DCTELEM)wsptr[4]); + + tmp13 = ((DCTELEM)wsptr[2] + (DCTELEM)wsptr[6]); + tmp12 = + MULTIPLY((DCTELEM)wsptr[2] - (DCTELEM)wsptr[6], FIX_1_414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = (DCTELEM)wsptr[5] + (DCTELEM)wsptr[3]; + z10 = (DCTELEM)wsptr[5] - (DCTELEM)wsptr[3]; + z11 = (DCTELEM)wsptr[1] + (DCTELEM)wsptr[7]; + z12 = (DCTELEM)wsptr[1] - (DCTELEM)wsptr[7]; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ + + z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ + tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ + tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = + range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS + 3) & RANGE_MASK]; + outptr[7] = + range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS + 3) & RANGE_MASK]; + outptr[1] = + range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS + 3) & RANGE_MASK]; + outptr[6] = + range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS + 3) & RANGE_MASK]; + outptr[2] = + range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS + 3) & RANGE_MASK]; + outptr[5] = + range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS + 3) & RANGE_MASK]; + outptr[4] = + range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS + 3) & RANGE_MASK]; + outptr[3] = + range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS + 3) & RANGE_MASK]; + + wsptr += DCTSIZE; /* advance pointer to next row */ + } +} + +#endif diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_Neon.c b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_Neon.c new file mode 100644 index 0000000000..5ccd6e154b --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_Neon.c @@ -0,0 +1,677 @@ +#import "DCTCommon.h" + +#include + +#if defined(__aarch64__) + +typedef long JLONG; + +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +typedef unsigned int JDIMENSION; + +#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */ + +#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */ +typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */ + +#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */ + +/* Various constants determining the sizes of things. + * All of these are specified by the JPEG standard, so don't change them + * if you want to be compatible. + */ + +#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ +#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ +#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ +#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ +#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ +#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ +#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ +/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard; + * the PostScript DCT filter can emit files with many more than 10 blocks/MCU. + * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU + * to handle it. We even let you do this from the jconfig.h file. However, + * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe + * sometimes emits noncompliant files doesn't mean you should too. + */ +#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */ +#ifndef D_MAX_BLOCKS_IN_MCU +#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */ +#endif + + +/* Data structures for images (arrays of samples and of DCT coefficients). + */ + +typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ +typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ + +typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ +typedef JBLOCK *JBLOCKROW; /* pointer to one row of coefficient blocks */ +typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ +typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ + +#include + +/* jsimd_idct_ifast_neon() performs dequantization and a fast, not so accurate + * inverse DCT (Discrete Cosine Transform) on one block of coefficients. It + * uses the same calculations and produces exactly the same output as IJG's + * original jpeg_idct_ifast() function, which can be found in jidctfst.c. + * + * Scaled integer constants are used to avoid floating-point arithmetic: + * 0.082392200 = 2688 * 2^-15 + * 0.414213562 = 13568 * 2^-15 + * 0.847759065 = 27776 * 2^-15 + * 0.613125930 = 20096 * 2^-15 + * + * See jidctfst.c for further details of the IDCT algorithm. Where possible, + * the variable names and comments here in jsimd_idct_ifast_neon() match up + * with those in jpeg_idct_ifast(). + */ + +#define PASS1_BITS 2 + +#define F_0_082 2688 +#define F_0_414 13568 +#define F_0_847 27776 +#define F_0_613 20096 + + +__attribute__((aligned(16))) static const int16_t jsimd_idct_ifast_neon_consts[] = { + F_0_082, F_0_414, F_0_847, F_0_613 +}; + +#define F_0_382 12544 +#define F_0_541 17792 +#define F_0_707 23168 +#define F_0_306 9984 + + +__attribute__((aligned(16))) static const int16_t jsimd_fdct_ifast_neon_consts[] = { + F_0_382, F_0_541, F_0_707, F_0_306 +}; + +void dct_jpeg_fdct_ifast(DCTELEM *data) { + /* Load an 8x8 block of samples into Neon registers. De-interleaving loads + * are used, followed by vuzp to transpose the block such that we have a + * column of samples per vector - allowing all rows to be processed at once. + */ + int16x8x4_t data1 = vld4q_s16(data); + int16x8x4_t data2 = vld4q_s16(data + 4 * DCTSIZE); + + int16x8x2_t cols_04 = vuzpq_s16(data1.val[0], data2.val[0]); + int16x8x2_t cols_15 = vuzpq_s16(data1.val[1], data2.val[1]); + int16x8x2_t cols_26 = vuzpq_s16(data1.val[2], data2.val[2]); + int16x8x2_t cols_37 = vuzpq_s16(data1.val[3], data2.val[3]); + + int16x8_t col0 = cols_04.val[0]; + int16x8_t col1 = cols_15.val[0]; + int16x8_t col2 = cols_26.val[0]; + int16x8_t col3 = cols_37.val[0]; + int16x8_t col4 = cols_04.val[1]; + int16x8_t col5 = cols_15.val[1]; + int16x8_t col6 = cols_26.val[1]; + int16x8_t col7 = cols_37.val[1]; + + /* Pass 1: process rows. */ + + /* Load DCT conversion constants. */ + const int16x4_t consts = vld1_s16(jsimd_fdct_ifast_neon_consts); + + int16x8_t tmp0 = vaddq_s16(col0, col7); + int16x8_t tmp7 = vsubq_s16(col0, col7); + int16x8_t tmp1 = vaddq_s16(col1, col6); + int16x8_t tmp6 = vsubq_s16(col1, col6); + int16x8_t tmp2 = vaddq_s16(col2, col5); + int16x8_t tmp5 = vsubq_s16(col2, col5); + int16x8_t tmp3 = vaddq_s16(col3, col4); + int16x8_t tmp4 = vsubq_s16(col3, col4); + + /* Even part */ + int16x8_t tmp10 = vaddq_s16(tmp0, tmp3); /* phase 2 */ + int16x8_t tmp13 = vsubq_s16(tmp0, tmp3); + int16x8_t tmp11 = vaddq_s16(tmp1, tmp2); + int16x8_t tmp12 = vsubq_s16(tmp1, tmp2); + + col0 = vaddq_s16(tmp10, tmp11); /* phase 3 */ + col4 = vsubq_s16(tmp10, tmp11); + + int16x8_t z1 = vqdmulhq_lane_s16(vaddq_s16(tmp12, tmp13), consts, 2); + col2 = vaddq_s16(tmp13, z1); /* phase 5 */ + col6 = vsubq_s16(tmp13, z1); + + /* Odd part */ + tmp10 = vaddq_s16(tmp4, tmp5); /* phase 2 */ + tmp11 = vaddq_s16(tmp5, tmp6); + tmp12 = vaddq_s16(tmp6, tmp7); + + int16x8_t z5 = vqdmulhq_lane_s16(vsubq_s16(tmp10, tmp12), consts, 0); + int16x8_t z2 = vqdmulhq_lane_s16(tmp10, consts, 1); + z2 = vaddq_s16(z2, z5); + int16x8_t z4 = vqdmulhq_lane_s16(tmp12, consts, 3); + z5 = vaddq_s16(tmp12, z5); + z4 = vaddq_s16(z4, z5); + int16x8_t z3 = vqdmulhq_lane_s16(tmp11, consts, 2); + + int16x8_t z11 = vaddq_s16(tmp7, z3); /* phase 5 */ + int16x8_t z13 = vsubq_s16(tmp7, z3); + + col5 = vaddq_s16(z13, z2); /* phase 6 */ + col3 = vsubq_s16(z13, z2); + col1 = vaddq_s16(z11, z4); + col7 = vsubq_s16(z11, z4); + + /* Transpose to work on columns in pass 2. */ + int16x8x2_t cols_01 = vtrnq_s16(col0, col1); + int16x8x2_t cols_23 = vtrnq_s16(col2, col3); + int16x8x2_t cols_45 = vtrnq_s16(col4, col5); + int16x8x2_t cols_67 = vtrnq_s16(col6, col7); + + int32x4x2_t cols_0145_l = vtrnq_s32(vreinterpretq_s32_s16(cols_01.val[0]), + vreinterpretq_s32_s16(cols_45.val[0])); + int32x4x2_t cols_0145_h = vtrnq_s32(vreinterpretq_s32_s16(cols_01.val[1]), + vreinterpretq_s32_s16(cols_45.val[1])); + int32x4x2_t cols_2367_l = vtrnq_s32(vreinterpretq_s32_s16(cols_23.val[0]), + vreinterpretq_s32_s16(cols_67.val[0])); + int32x4x2_t cols_2367_h = vtrnq_s32(vreinterpretq_s32_s16(cols_23.val[1]), + vreinterpretq_s32_s16(cols_67.val[1])); + + int32x4x2_t rows_04 = vzipq_s32(cols_0145_l.val[0], cols_2367_l.val[0]); + int32x4x2_t rows_15 = vzipq_s32(cols_0145_h.val[0], cols_2367_h.val[0]); + int32x4x2_t rows_26 = vzipq_s32(cols_0145_l.val[1], cols_2367_l.val[1]); + int32x4x2_t rows_37 = vzipq_s32(cols_0145_h.val[1], cols_2367_h.val[1]); + + int16x8_t row0 = vreinterpretq_s16_s32(rows_04.val[0]); + int16x8_t row1 = vreinterpretq_s16_s32(rows_15.val[0]); + int16x8_t row2 = vreinterpretq_s16_s32(rows_26.val[0]); + int16x8_t row3 = vreinterpretq_s16_s32(rows_37.val[0]); + int16x8_t row4 = vreinterpretq_s16_s32(rows_04.val[1]); + int16x8_t row5 = vreinterpretq_s16_s32(rows_15.val[1]); + int16x8_t row6 = vreinterpretq_s16_s32(rows_26.val[1]); + int16x8_t row7 = vreinterpretq_s16_s32(rows_37.val[1]); + + /* Pass 2: process columns. */ + + tmp0 = vaddq_s16(row0, row7); + tmp7 = vsubq_s16(row0, row7); + tmp1 = vaddq_s16(row1, row6); + tmp6 = vsubq_s16(row1, row6); + tmp2 = vaddq_s16(row2, row5); + tmp5 = vsubq_s16(row2, row5); + tmp3 = vaddq_s16(row3, row4); + tmp4 = vsubq_s16(row3, row4); + + /* Even part */ + tmp10 = vaddq_s16(tmp0, tmp3); /* phase 2 */ + tmp13 = vsubq_s16(tmp0, tmp3); + tmp11 = vaddq_s16(tmp1, tmp2); + tmp12 = vsubq_s16(tmp1, tmp2); + + row0 = vaddq_s16(tmp10, tmp11); /* phase 3 */ + row4 = vsubq_s16(tmp10, tmp11); + + z1 = vqdmulhq_lane_s16(vaddq_s16(tmp12, tmp13), consts, 2); + row2 = vaddq_s16(tmp13, z1); /* phase 5 */ + row6 = vsubq_s16(tmp13, z1); + + /* Odd part */ + tmp10 = vaddq_s16(tmp4, tmp5); /* phase 2 */ + tmp11 = vaddq_s16(tmp5, tmp6); + tmp12 = vaddq_s16(tmp6, tmp7); + + z5 = vqdmulhq_lane_s16(vsubq_s16(tmp10, tmp12), consts, 0); + z2 = vqdmulhq_lane_s16(tmp10, consts, 1); + z2 = vaddq_s16(z2, z5); + z4 = vqdmulhq_lane_s16(tmp12, consts, 3); + z5 = vaddq_s16(tmp12, z5); + z4 = vaddq_s16(z4, z5); + z3 = vqdmulhq_lane_s16(tmp11, consts, 2); + + z11 = vaddq_s16(tmp7, z3); /* phase 5 */ + z13 = vsubq_s16(tmp7, z3); + + row5 = vaddq_s16(z13, z2); /* phase 6 */ + row3 = vsubq_s16(z13, z2); + row1 = vaddq_s16(z11, z4); + row7 = vsubq_s16(z11, z4); + + vst1q_s16(data + 0 * DCTSIZE, row0); + vst1q_s16(data + 1 * DCTSIZE, row1); + vst1q_s16(data + 2 * DCTSIZE, row2); + vst1q_s16(data + 3 * DCTSIZE, row3); + vst1q_s16(data + 4 * DCTSIZE, row4); + vst1q_s16(data + 5 * DCTSIZE, row5); + vst1q_s16(data + 6 * DCTSIZE, row6); + vst1q_s16(data + 7 * DCTSIZE, row7); +} + +struct DctAuxiliaryData { +}; + +struct DctAuxiliaryData *createDctAuxiliaryData() { + struct DctAuxiliaryData *result = malloc(sizeof(struct DctAuxiliaryData)); + return result; +} + +void freeDctAuxiliaryData(struct DctAuxiliaryData *data) { + if (data) { + free(data); + } +} + +void dct_jpeg_idct_ifast(struct DctAuxiliaryData *auxiliaryData, void *dct_table, JCOEFPTR coef_block, JSAMPROW output_buf) +{ + IFAST_MULT_TYPE *quantptr = dct_table; + + /* Load DCT coefficients. */ + int16x8_t row0 = vld1q_s16(coef_block + 0 * DCTSIZE); + int16x8_t row1 = vld1q_s16(coef_block + 1 * DCTSIZE); + int16x8_t row2 = vld1q_s16(coef_block + 2 * DCTSIZE); + int16x8_t row3 = vld1q_s16(coef_block + 3 * DCTSIZE); + int16x8_t row4 = vld1q_s16(coef_block + 4 * DCTSIZE); + int16x8_t row5 = vld1q_s16(coef_block + 5 * DCTSIZE); + int16x8_t row6 = vld1q_s16(coef_block + 6 * DCTSIZE); + int16x8_t row7 = vld1q_s16(coef_block + 7 * DCTSIZE); + + /* Load quantization table values for DC coefficients. */ + int16x8_t quant_row0 = vld1q_s16(quantptr + 0 * DCTSIZE); + /* Dequantize DC coefficients. */ + row0 = vmulq_s16(row0, quant_row0); + + /* Construct bitmap to test if all AC coefficients are 0. */ + int16x8_t bitmap = vorrq_s16(row1, row2); + bitmap = vorrq_s16(bitmap, row3); + bitmap = vorrq_s16(bitmap, row4); + bitmap = vorrq_s16(bitmap, row5); + bitmap = vorrq_s16(bitmap, row6); + bitmap = vorrq_s16(bitmap, row7); + + int64_t left_ac_bitmap = vgetq_lane_s64(vreinterpretq_s64_s16(bitmap), 0); + int64_t right_ac_bitmap = vgetq_lane_s64(vreinterpretq_s64_s16(bitmap), 1); + + /* Load IDCT conversion constants. */ + const int16x4_t consts = vld1_s16(jsimd_idct_ifast_neon_consts); + + if (left_ac_bitmap == 0 && right_ac_bitmap == 0) { + /* All AC coefficients are zero. + * Compute DC values and duplicate into vectors. + */ + int16x8_t dcval = row0; + row1 = dcval; + row2 = dcval; + row3 = dcval; + row4 = dcval; + row5 = dcval; + row6 = dcval; + row7 = dcval; + } else if (left_ac_bitmap == 0) { + /* AC coefficients are zero for columns 0, 1, 2, and 3. + * Use DC values for these columns. + */ + int16x4_t dcval = vget_low_s16(row0); + + /* Commence regular fast IDCT computation for columns 4, 5, 6, and 7. */ + + /* Load quantization table. */ + int16x4_t quant_row1 = vld1_s16(quantptr + 1 * DCTSIZE + 4); + int16x4_t quant_row2 = vld1_s16(quantptr + 2 * DCTSIZE + 4); + int16x4_t quant_row3 = vld1_s16(quantptr + 3 * DCTSIZE + 4); + int16x4_t quant_row4 = vld1_s16(quantptr + 4 * DCTSIZE + 4); + int16x4_t quant_row5 = vld1_s16(quantptr + 5 * DCTSIZE + 4); + int16x4_t quant_row6 = vld1_s16(quantptr + 6 * DCTSIZE + 4); + int16x4_t quant_row7 = vld1_s16(quantptr + 7 * DCTSIZE + 4); + + /* Even part: dequantize DCT coefficients. */ + int16x4_t tmp0 = vget_high_s16(row0); + int16x4_t tmp1 = vmul_s16(vget_high_s16(row2), quant_row2); + int16x4_t tmp2 = vmul_s16(vget_high_s16(row4), quant_row4); + int16x4_t tmp3 = vmul_s16(vget_high_s16(row6), quant_row6); + + int16x4_t tmp10 = vadd_s16(tmp0, tmp2); /* phase 3 */ + int16x4_t tmp11 = vsub_s16(tmp0, tmp2); + + int16x4_t tmp13 = vadd_s16(tmp1, tmp3); /* phases 5-3 */ + int16x4_t tmp1_sub_tmp3 = vsub_s16(tmp1, tmp3); + int16x4_t tmp12 = vqdmulh_lane_s16(tmp1_sub_tmp3, consts, 1); + tmp12 = vadd_s16(tmp12, tmp1_sub_tmp3); + tmp12 = vsub_s16(tmp12, tmp13); + + tmp0 = vadd_s16(tmp10, tmp13); /* phase 2 */ + tmp3 = vsub_s16(tmp10, tmp13); + tmp1 = vadd_s16(tmp11, tmp12); + tmp2 = vsub_s16(tmp11, tmp12); + + /* Odd part: dequantize DCT coefficients. */ + int16x4_t tmp4 = vmul_s16(vget_high_s16(row1), quant_row1); + int16x4_t tmp5 = vmul_s16(vget_high_s16(row3), quant_row3); + int16x4_t tmp6 = vmul_s16(vget_high_s16(row5), quant_row5); + int16x4_t tmp7 = vmul_s16(vget_high_s16(row7), quant_row7); + + int16x4_t z13 = vadd_s16(tmp6, tmp5); /* phase 6 */ + int16x4_t neg_z10 = vsub_s16(tmp5, tmp6); + int16x4_t z11 = vadd_s16(tmp4, tmp7); + int16x4_t z12 = vsub_s16(tmp4, tmp7); + + tmp7 = vadd_s16(z11, z13); /* phase 5 */ + int16x4_t z11_sub_z13 = vsub_s16(z11, z13); + tmp11 = vqdmulh_lane_s16(z11_sub_z13, consts, 1); + tmp11 = vadd_s16(tmp11, z11_sub_z13); + + int16x4_t z10_add_z12 = vsub_s16(z12, neg_z10); + int16x4_t z5 = vqdmulh_lane_s16(z10_add_z12, consts, 2); + z5 = vadd_s16(z5, z10_add_z12); + tmp10 = vqdmulh_lane_s16(z12, consts, 0); + tmp10 = vadd_s16(tmp10, z12); + tmp10 = vsub_s16(tmp10, z5); + tmp12 = vqdmulh_lane_s16(neg_z10, consts, 3); + tmp12 = vadd_s16(tmp12, vadd_s16(neg_z10, neg_z10)); + tmp12 = vadd_s16(tmp12, z5); + + tmp6 = vsub_s16(tmp12, tmp7); /* phase 2 */ + tmp5 = vsub_s16(tmp11, tmp6); + tmp4 = vadd_s16(tmp10, tmp5); + + row0 = vcombine_s16(dcval, vadd_s16(tmp0, tmp7)); + row7 = vcombine_s16(dcval, vsub_s16(tmp0, tmp7)); + row1 = vcombine_s16(dcval, vadd_s16(tmp1, tmp6)); + row6 = vcombine_s16(dcval, vsub_s16(tmp1, tmp6)); + row2 = vcombine_s16(dcval, vadd_s16(tmp2, tmp5)); + row5 = vcombine_s16(dcval, vsub_s16(tmp2, tmp5)); + row4 = vcombine_s16(dcval, vadd_s16(tmp3, tmp4)); + row3 = vcombine_s16(dcval, vsub_s16(tmp3, tmp4)); + } else if (right_ac_bitmap == 0) { + /* AC coefficients are zero for columns 4, 5, 6, and 7. + * Use DC values for these columns. + */ + int16x4_t dcval = vget_high_s16(row0); + + /* Commence regular fast IDCT computation for columns 0, 1, 2, and 3. */ + + /* Load quantization table. */ + int16x4_t quant_row1 = vld1_s16(quantptr + 1 * DCTSIZE); + int16x4_t quant_row2 = vld1_s16(quantptr + 2 * DCTSIZE); + int16x4_t quant_row3 = vld1_s16(quantptr + 3 * DCTSIZE); + int16x4_t quant_row4 = vld1_s16(quantptr + 4 * DCTSIZE); + int16x4_t quant_row5 = vld1_s16(quantptr + 5 * DCTSIZE); + int16x4_t quant_row6 = vld1_s16(quantptr + 6 * DCTSIZE); + int16x4_t quant_row7 = vld1_s16(quantptr + 7 * DCTSIZE); + + /* Even part: dequantize DCT coefficients. */ + int16x4_t tmp0 = vget_low_s16(row0); + int16x4_t tmp1 = vmul_s16(vget_low_s16(row2), quant_row2); + int16x4_t tmp2 = vmul_s16(vget_low_s16(row4), quant_row4); + int16x4_t tmp3 = vmul_s16(vget_low_s16(row6), quant_row6); + + int16x4_t tmp10 = vadd_s16(tmp0, tmp2); /* phase 3 */ + int16x4_t tmp11 = vsub_s16(tmp0, tmp2); + + int16x4_t tmp13 = vadd_s16(tmp1, tmp3); /* phases 5-3 */ + int16x4_t tmp1_sub_tmp3 = vsub_s16(tmp1, tmp3); + int16x4_t tmp12 = vqdmulh_lane_s16(tmp1_sub_tmp3, consts, 1); + tmp12 = vadd_s16(tmp12, tmp1_sub_tmp3); + tmp12 = vsub_s16(tmp12, tmp13); + + tmp0 = vadd_s16(tmp10, tmp13); /* phase 2 */ + tmp3 = vsub_s16(tmp10, tmp13); + tmp1 = vadd_s16(tmp11, tmp12); + tmp2 = vsub_s16(tmp11, tmp12); + + /* Odd part: dequantize DCT coefficients. */ + int16x4_t tmp4 = vmul_s16(vget_low_s16(row1), quant_row1); + int16x4_t tmp5 = vmul_s16(vget_low_s16(row3), quant_row3); + int16x4_t tmp6 = vmul_s16(vget_low_s16(row5), quant_row5); + int16x4_t tmp7 = vmul_s16(vget_low_s16(row7), quant_row7); + + int16x4_t z13 = vadd_s16(tmp6, tmp5); /* phase 6 */ + int16x4_t neg_z10 = vsub_s16(tmp5, tmp6); + int16x4_t z11 = vadd_s16(tmp4, tmp7); + int16x4_t z12 = vsub_s16(tmp4, tmp7); + + tmp7 = vadd_s16(z11, z13); /* phase 5 */ + int16x4_t z11_sub_z13 = vsub_s16(z11, z13); + tmp11 = vqdmulh_lane_s16(z11_sub_z13, consts, 1); + tmp11 = vadd_s16(tmp11, z11_sub_z13); + + int16x4_t z10_add_z12 = vsub_s16(z12, neg_z10); + int16x4_t z5 = vqdmulh_lane_s16(z10_add_z12, consts, 2); + z5 = vadd_s16(z5, z10_add_z12); + tmp10 = vqdmulh_lane_s16(z12, consts, 0); + tmp10 = vadd_s16(tmp10, z12); + tmp10 = vsub_s16(tmp10, z5); + tmp12 = vqdmulh_lane_s16(neg_z10, consts, 3); + tmp12 = vadd_s16(tmp12, vadd_s16(neg_z10, neg_z10)); + tmp12 = vadd_s16(tmp12, z5); + + tmp6 = vsub_s16(tmp12, tmp7); /* phase 2 */ + tmp5 = vsub_s16(tmp11, tmp6); + tmp4 = vadd_s16(tmp10, tmp5); + + row0 = vcombine_s16(vadd_s16(tmp0, tmp7), dcval); + row7 = vcombine_s16(vsub_s16(tmp0, tmp7), dcval); + row1 = vcombine_s16(vadd_s16(tmp1, tmp6), dcval); + row6 = vcombine_s16(vsub_s16(tmp1, tmp6), dcval); + row2 = vcombine_s16(vadd_s16(tmp2, tmp5), dcval); + row5 = vcombine_s16(vsub_s16(tmp2, tmp5), dcval); + row4 = vcombine_s16(vadd_s16(tmp3, tmp4), dcval); + row3 = vcombine_s16(vsub_s16(tmp3, tmp4), dcval); + } else { + /* Some AC coefficients are non-zero; full IDCT calculation required. */ + + /* Load quantization table. */ + int16x8_t quant_row1 = vld1q_s16(quantptr + 1 * DCTSIZE); + int16x8_t quant_row2 = vld1q_s16(quantptr + 2 * DCTSIZE); + int16x8_t quant_row3 = vld1q_s16(quantptr + 3 * DCTSIZE); + int16x8_t quant_row4 = vld1q_s16(quantptr + 4 * DCTSIZE); + int16x8_t quant_row5 = vld1q_s16(quantptr + 5 * DCTSIZE); + int16x8_t quant_row6 = vld1q_s16(quantptr + 6 * DCTSIZE); + int16x8_t quant_row7 = vld1q_s16(quantptr + 7 * DCTSIZE); + + /* Even part: dequantize DCT coefficients. */ + int16x8_t tmp0 = row0; + int16x8_t tmp1 = vmulq_s16(row2, quant_row2); + int16x8_t tmp2 = vmulq_s16(row4, quant_row4); + int16x8_t tmp3 = vmulq_s16(row6, quant_row6); + + int16x8_t tmp10 = vaddq_s16(tmp0, tmp2); /* phase 3 */ + int16x8_t tmp11 = vsubq_s16(tmp0, tmp2); + + int16x8_t tmp13 = vaddq_s16(tmp1, tmp3); /* phases 5-3 */ + int16x8_t tmp1_sub_tmp3 = vsubq_s16(tmp1, tmp3); + int16x8_t tmp12 = vqdmulhq_lane_s16(tmp1_sub_tmp3, consts, 1); + tmp12 = vaddq_s16(tmp12, tmp1_sub_tmp3); + tmp12 = vsubq_s16(tmp12, tmp13); + + tmp0 = vaddq_s16(tmp10, tmp13); /* phase 2 */ + tmp3 = vsubq_s16(tmp10, tmp13); + tmp1 = vaddq_s16(tmp11, tmp12); + tmp2 = vsubq_s16(tmp11, tmp12); + + /* Odd part: dequantize DCT coefficients. */ + int16x8_t tmp4 = vmulq_s16(row1, quant_row1); + int16x8_t tmp5 = vmulq_s16(row3, quant_row3); + int16x8_t tmp6 = vmulq_s16(row5, quant_row5); + int16x8_t tmp7 = vmulq_s16(row7, quant_row7); + + int16x8_t z13 = vaddq_s16(tmp6, tmp5); /* phase 6 */ + int16x8_t neg_z10 = vsubq_s16(tmp5, tmp6); + int16x8_t z11 = vaddq_s16(tmp4, tmp7); + int16x8_t z12 = vsubq_s16(tmp4, tmp7); + + tmp7 = vaddq_s16(z11, z13); /* phase 5 */ + int16x8_t z11_sub_z13 = vsubq_s16(z11, z13); + tmp11 = vqdmulhq_lane_s16(z11_sub_z13, consts, 1); + tmp11 = vaddq_s16(tmp11, z11_sub_z13); + + int16x8_t z10_add_z12 = vsubq_s16(z12, neg_z10); + int16x8_t z5 = vqdmulhq_lane_s16(z10_add_z12, consts, 2); + z5 = vaddq_s16(z5, z10_add_z12); + tmp10 = vqdmulhq_lane_s16(z12, consts, 0); + tmp10 = vaddq_s16(tmp10, z12); + tmp10 = vsubq_s16(tmp10, z5); + tmp12 = vqdmulhq_lane_s16(neg_z10, consts, 3); + tmp12 = vaddq_s16(tmp12, vaddq_s16(neg_z10, neg_z10)); + tmp12 = vaddq_s16(tmp12, z5); + + tmp6 = vsubq_s16(tmp12, tmp7); /* phase 2 */ + tmp5 = vsubq_s16(tmp11, tmp6); + tmp4 = vaddq_s16(tmp10, tmp5); + + row0 = vaddq_s16(tmp0, tmp7); + row7 = vsubq_s16(tmp0, tmp7); + row1 = vaddq_s16(tmp1, tmp6); + row6 = vsubq_s16(tmp1, tmp6); + row2 = vaddq_s16(tmp2, tmp5); + row5 = vsubq_s16(tmp2, tmp5); + row4 = vaddq_s16(tmp3, tmp4); + row3 = vsubq_s16(tmp3, tmp4); + } + + /* Transpose rows to work on columns in pass 2. */ + int16x8x2_t rows_01 = vtrnq_s16(row0, row1); + int16x8x2_t rows_23 = vtrnq_s16(row2, row3); + int16x8x2_t rows_45 = vtrnq_s16(row4, row5); + int16x8x2_t rows_67 = vtrnq_s16(row6, row7); + + int32x4x2_t rows_0145_l = vtrnq_s32(vreinterpretq_s32_s16(rows_01.val[0]), + vreinterpretq_s32_s16(rows_45.val[0])); + int32x4x2_t rows_0145_h = vtrnq_s32(vreinterpretq_s32_s16(rows_01.val[1]), + vreinterpretq_s32_s16(rows_45.val[1])); + int32x4x2_t rows_2367_l = vtrnq_s32(vreinterpretq_s32_s16(rows_23.val[0]), + vreinterpretq_s32_s16(rows_67.val[0])); + int32x4x2_t rows_2367_h = vtrnq_s32(vreinterpretq_s32_s16(rows_23.val[1]), + vreinterpretq_s32_s16(rows_67.val[1])); + + int32x4x2_t cols_04 = vzipq_s32(rows_0145_l.val[0], rows_2367_l.val[0]); + int32x4x2_t cols_15 = vzipq_s32(rows_0145_h.val[0], rows_2367_h.val[0]); + int32x4x2_t cols_26 = vzipq_s32(rows_0145_l.val[1], rows_2367_l.val[1]); + int32x4x2_t cols_37 = vzipq_s32(rows_0145_h.val[1], rows_2367_h.val[1]); + + int16x8_t col0 = vreinterpretq_s16_s32(cols_04.val[0]); + int16x8_t col1 = vreinterpretq_s16_s32(cols_15.val[0]); + int16x8_t col2 = vreinterpretq_s16_s32(cols_26.val[0]); + int16x8_t col3 = vreinterpretq_s16_s32(cols_37.val[0]); + int16x8_t col4 = vreinterpretq_s16_s32(cols_04.val[1]); + int16x8_t col5 = vreinterpretq_s16_s32(cols_15.val[1]); + int16x8_t col6 = vreinterpretq_s16_s32(cols_26.val[1]); + int16x8_t col7 = vreinterpretq_s16_s32(cols_37.val[1]); + + /* 1-D IDCT, pass 2 */ + + /* Even part */ + int16x8_t tmp10 = vaddq_s16(col0, col4); + int16x8_t tmp11 = vsubq_s16(col0, col4); + + int16x8_t tmp13 = vaddq_s16(col2, col6); + int16x8_t col2_sub_col6 = vsubq_s16(col2, col6); + int16x8_t tmp12 = vqdmulhq_lane_s16(col2_sub_col6, consts, 1); + tmp12 = vaddq_s16(tmp12, col2_sub_col6); + tmp12 = vsubq_s16(tmp12, tmp13); + + int16x8_t tmp0 = vaddq_s16(tmp10, tmp13); + int16x8_t tmp3 = vsubq_s16(tmp10, tmp13); + int16x8_t tmp1 = vaddq_s16(tmp11, tmp12); + int16x8_t tmp2 = vsubq_s16(tmp11, tmp12); + + /* Odd part */ + int16x8_t z13 = vaddq_s16(col5, col3); + int16x8_t neg_z10 = vsubq_s16(col3, col5); + int16x8_t z11 = vaddq_s16(col1, col7); + int16x8_t z12 = vsubq_s16(col1, col7); + + int16x8_t tmp7 = vaddq_s16(z11, z13); /* phase 5 */ + int16x8_t z11_sub_z13 = vsubq_s16(z11, z13); + tmp11 = vqdmulhq_lane_s16(z11_sub_z13, consts, 1); + tmp11 = vaddq_s16(tmp11, z11_sub_z13); + + int16x8_t z10_add_z12 = vsubq_s16(z12, neg_z10); + int16x8_t z5 = vqdmulhq_lane_s16(z10_add_z12, consts, 2); + z5 = vaddq_s16(z5, z10_add_z12); + tmp10 = vqdmulhq_lane_s16(z12, consts, 0); + tmp10 = vaddq_s16(tmp10, z12); + tmp10 = vsubq_s16(tmp10, z5); + tmp12 = vqdmulhq_lane_s16(neg_z10, consts, 3); + tmp12 = vaddq_s16(tmp12, vaddq_s16(neg_z10, neg_z10)); + tmp12 = vaddq_s16(tmp12, z5); + + int16x8_t tmp6 = vsubq_s16(tmp12, tmp7); /* phase 2 */ + int16x8_t tmp5 = vsubq_s16(tmp11, tmp6); + int16x8_t tmp4 = vaddq_s16(tmp10, tmp5); + + col0 = vaddq_s16(tmp0, tmp7); + col7 = vsubq_s16(tmp0, tmp7); + col1 = vaddq_s16(tmp1, tmp6); + col6 = vsubq_s16(tmp1, tmp6); + col2 = vaddq_s16(tmp2, tmp5); + col5 = vsubq_s16(tmp2, tmp5); + col4 = vaddq_s16(tmp3, tmp4); + col3 = vsubq_s16(tmp3, tmp4); + + /* Scale down by a factor of 8, narrowing to 8-bit. */ + int8x16_t cols_01_s8 = vcombine_s8(vqshrn_n_s16(col0, PASS1_BITS + 3), + vqshrn_n_s16(col1, PASS1_BITS + 3)); + int8x16_t cols_45_s8 = vcombine_s8(vqshrn_n_s16(col4, PASS1_BITS + 3), + vqshrn_n_s16(col5, PASS1_BITS + 3)); + int8x16_t cols_23_s8 = vcombine_s8(vqshrn_n_s16(col2, PASS1_BITS + 3), + vqshrn_n_s16(col3, PASS1_BITS + 3)); + int8x16_t cols_67_s8 = vcombine_s8(vqshrn_n_s16(col6, PASS1_BITS + 3), + vqshrn_n_s16(col7, PASS1_BITS + 3)); + /* Clamp to range [0-255]. */ + uint8x16_t cols_01 = + vreinterpretq_u8_s8 + (vaddq_s8(cols_01_s8, vreinterpretq_s8_u8(vdupq_n_u8(CENTERJSAMPLE)))); + uint8x16_t cols_45 = + vreinterpretq_u8_s8 + (vaddq_s8(cols_45_s8, vreinterpretq_s8_u8(vdupq_n_u8(CENTERJSAMPLE)))); + uint8x16_t cols_23 = + vreinterpretq_u8_s8 + (vaddq_s8(cols_23_s8, vreinterpretq_s8_u8(vdupq_n_u8(CENTERJSAMPLE)))); + uint8x16_t cols_67 = + vreinterpretq_u8_s8 + (vaddq_s8(cols_67_s8, vreinterpretq_s8_u8(vdupq_n_u8(CENTERJSAMPLE)))); + + /* Transpose block to prepare for store. */ + uint32x4x2_t cols_0415 = vzipq_u32(vreinterpretq_u32_u8(cols_01), + vreinterpretq_u32_u8(cols_45)); + uint32x4x2_t cols_2637 = vzipq_u32(vreinterpretq_u32_u8(cols_23), + vreinterpretq_u32_u8(cols_67)); + + uint8x16x2_t cols_0145 = vtrnq_u8(vreinterpretq_u8_u32(cols_0415.val[0]), + vreinterpretq_u8_u32(cols_0415.val[1])); + uint8x16x2_t cols_2367 = vtrnq_u8(vreinterpretq_u8_u32(cols_2637.val[0]), + vreinterpretq_u8_u32(cols_2637.val[1])); + uint16x8x2_t rows_0426 = vtrnq_u16(vreinterpretq_u16_u8(cols_0145.val[0]), + vreinterpretq_u16_u8(cols_2367.val[0])); + uint16x8x2_t rows_1537 = vtrnq_u16(vreinterpretq_u16_u8(cols_0145.val[1]), + vreinterpretq_u16_u8(cols_2367.val[1])); + + uint8x16_t rows_04 = vreinterpretq_u8_u16(rows_0426.val[0]); + uint8x16_t rows_15 = vreinterpretq_u8_u16(rows_1537.val[0]); + uint8x16_t rows_26 = vreinterpretq_u8_u16(rows_0426.val[1]); + uint8x16_t rows_37 = vreinterpretq_u8_u16(rows_1537.val[1]); + + JSAMPROW outptr0 = output_buf + DCTSIZE * 0; + JSAMPROW outptr1 = output_buf + DCTSIZE * 1; + JSAMPROW outptr2 = output_buf + DCTSIZE * 2; + JSAMPROW outptr3 = output_buf + DCTSIZE * 3; + JSAMPROW outptr4 = output_buf + DCTSIZE * 4; + JSAMPROW outptr5 = output_buf + DCTSIZE * 5; + JSAMPROW outptr6 = output_buf + DCTSIZE * 6; + JSAMPROW outptr7 = output_buf + DCTSIZE * 7; + + /* Store DCT block to memory. */ + vst1q_lane_u64((uint64_t *)outptr0, vreinterpretq_u64_u8(rows_04), 0); + vst1q_lane_u64((uint64_t *)outptr1, vreinterpretq_u64_u8(rows_15), 0); + vst1q_lane_u64((uint64_t *)outptr2, vreinterpretq_u64_u8(rows_26), 0); + vst1q_lane_u64((uint64_t *)outptr3, vreinterpretq_u64_u8(rows_37), 0); + vst1q_lane_u64((uint64_t *)outptr4, vreinterpretq_u64_u8(rows_04), 1); + vst1q_lane_u64((uint64_t *)outptr5, vreinterpretq_u64_u8(rows_15), 1); + vst1q_lane_u64((uint64_t *)outptr6, vreinterpretq_u64_u8(rows_26), 1); + vst1q_lane_u64((uint64_t *)outptr7, vreinterpretq_u64_u8(rows_37), 1); +} + +#endif diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm new file mode 100644 index 0000000000..8a50b55c4b --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm @@ -0,0 +1,66 @@ +#import + +#import + +#include "DCT.h" + +@interface ImageDCTTable () { +@public + dct::DCTTable _table; +} + +@end + +@implementation ImageDCTTable + +- (instancetype _Nonnull)initWithQuality:(NSInteger)quality isChroma:(bool)isChroma { + self = [super init]; + if (self != nil) { + _table = dct::DCTTable::generate((int)quality, isChroma); + } + return self; +} + +- (instancetype _Nullable)initWithData:(NSData * _Nonnull)data { + self = [super init]; + if (self != nil) { + _table = dct::DCTTable::initializeEmpty(); + if (data.length != _table.table.size() * 2) { + return nil; + } + memcpy(_table.table.data(), data.bytes, data.length); + } + return self; +} + +- (NSData * _Nonnull)serializedData { + return [[NSData alloc] initWithBytes:_table.table.data() length:_table.table.size() * 2]; +} + +@end + +@interface ImageDCT () { + std::unique_ptr _dct; +} + +@end + +@implementation ImageDCT + +- (instancetype _Nonnull)initWithTable:(ImageDCTTable * _Nonnull)table { + self = [super init]; + if (self != nil) { + _dct = std::unique_ptr(new dct::DCT(table->_table)); + } + return self; +} + +- (void)forwardWithPixels:(uint8_t const * _Nonnull)pixels coefficients:(int16_t * _Nonnull)coefficients width:(NSInteger)width height:(NSInteger)height bytesPerRow:(NSInteger)bytesPerRow { + _dct->forward(pixels, coefficients, (int)width, (int)height, (int)bytesPerRow); +} + +- (void)inverseWithCoefficients:(int16_t const * _Nonnull)coefficients pixels:(uint8_t * _Nonnull)pixels width:(NSInteger)width height:(NSInteger)height coefficientsPerRow:(NSInteger)coefficientsPerRow bytesPerRow:(NSInteger)bytesPerRow { + _dct->inverse(coefficients, pixels, (int)width, (int)height, (int)coefficientsPerRow, (int)bytesPerRow); +} + +@end diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m new file mode 100644 index 0000000000..0851a92c91 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m @@ -0,0 +1,115 @@ +#import + +#import +#import + +static uint8_t permuteMap[4] = { 3, 2, 1, 0}; + +void splitRGBAIntoYUVAPlanes(uint8_t const *argb, uint8_t *outY, uint8_t *outU, uint8_t *outV, uint8_t *outA, int width, int height, int bytesPerRow) { + static vImage_ARGBToYpCbCr info; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 1, 255, 0 }; + vImageConvert_ARGBToYpCbCr_GenerateConversion(kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2, &pixelRange, &info, kvImageARGB8888, kvImage420Yp8_Cb8_Cr8, 0); + }); + + vImage_Error error = kvImageNoError; + + vImage_Buffer src; + src.data = (void *)argb; + src.width = width; + src.height = height; + src.rowBytes = bytesPerRow; + + vImage_Buffer destYp; + destYp.data = outY; + destYp.width = width; + destYp.height = height; + destYp.rowBytes = width; + + vImage_Buffer destCr; + destCr.data = outU; + destCr.width = width / 2; + destCr.height = height / 2; + destCr.rowBytes = width / 2; + + vImage_Buffer destCb; + destCb.data = outV; + destCb.width = width / 2; + destCb.height = height / 2; + destCb.rowBytes = width / 2; + + vImage_Buffer destA; + destA.data = outA; + destA.width = width; + destA.height = height; + destA.rowBytes = width; + + error = vImageConvert_ARGB8888To420Yp8_Cb8_Cr8(&src, &destYp, &destCb, &destCr, &info, permuteMap, kvImageDoNotTile); + if (error != kvImageNoError) { + return; + } + + vImageExtractChannel_ARGB8888(&src, &destA, 3, kvImageDoNotTile); +} + +void combineYUVAPlanesIntoARBB(uint8_t *argb, uint8_t const *inY, uint8_t const *inU, uint8_t const *inV, uint8_t const *inA, int width, int height, int bytesPerRow) { + static vImage_YpCbCrToARGB info; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + vImage_YpCbCrPixelRange pixelRange = (vImage_YpCbCrPixelRange){ 0, 128, 255, 255, 255, 1, 255, 0 }; + vImageConvert_YpCbCrToARGB_GenerateConversion(kvImage_YpCbCrToARGBMatrix_ITU_R_709_2, &pixelRange, &info, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, 0); + }); + + vImage_Error error = kvImageNoError; + + vImage_Buffer destArgb; + destArgb.data = (void *)argb; + destArgb.width = width; + destArgb.height = height; + destArgb.rowBytes = bytesPerRow; + + vImage_Buffer srcYp; + srcYp.data = (void *)inY; + srcYp.width = width; + srcYp.height = height; + srcYp.rowBytes = width; + + vImage_Buffer srcCr; + srcCr.data = (void *)inU; + srcCr.width = width / 2; + srcCr.height = height / 2; + srcCr.rowBytes = width / 2; + + vImage_Buffer srcCb; + srcCb.data = (void *)inV; + srcCb.width = width / 2; + srcCb.height = height / 2; + srcCb.rowBytes = width / 2; + + vImage_Buffer srcA; + srcA.data = (void *)inA; + srcA.width = width; + srcA.height = height; + srcA.rowBytes = width; + + error = vImageConvert_420Yp8_Cb8_Cr8ToARGB8888(&srcYp, &srcCb, &srcCr, &destArgb, &info, permuteMap, 255, kvImageDoNotTile); + + error = vImageOverwriteChannels_ARGB8888(&srcA, &destArgb, &destArgb, 1 << 0, kvImageDoNotTile); +} + +void scaleImagePlane(uint8_t *outPlane, int outWidth, int outHeight, int outBytesPerRow, uint8_t const *inPlane, int inWidth, int inHeight, int inBytesPerRow) { + vImage_Buffer src; + src.data = (void *)inPlane; + src.width = inWidth; + src.height = inHeight; + src.rowBytes = inBytesPerRow; + + vImage_Buffer dst; + dst.data = (void *)outPlane; + dst.width = outWidth; + dst.height = outHeight; + dst.rowBytes = outBytesPerRow; + + vImageScale_Planar8(&src, &dst, nil, kvImageDoNotTile); +} diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 819d57826a..93d442d7f9 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -3,47 +3,112 @@ import UIKit import SwiftSignalKit import CryptoUtils import ManagedFile +import Compression + +private func alignUp(size: Int, align: Int) -> Int { + precondition(((align - 1) & align) == 0, "Align must be a power of two") + + let alignmentMask = align - 1 + return (size + alignmentMask) & ~alignmentMask +} public final class AnimationCacheItemFrame { - public enum Format { - case rgba(width: Int, height: Int, bytesPerRow: Int) + public enum RequestedFormat { + case rgba + case yuva(rowAlignment: Int) + } + + public final class Plane { + public let data: Data + public let width: Int + public let height: Int + public let bytesPerRow: Int + + public init(data: Data, width: Int, height: Int, bytesPerRow: Int) { + self.data = data + self.width = width + self.height = height + self.bytesPerRow = bytesPerRow + } + } + + public enum Format { + case rgba(data: Data, width: Int, height: Int, bytesPerRow: Int) + case yuva(y: Plane, u: Plane, v: Plane, a: Plane) } - public let data: Data - public let range: Range public let format: Format public let duration: Double - public init(data: Data, range: Range, format: Format, duration: Double) { - self.data = data - self.range = range + public init(format: Format, duration: Double) { self.format = format self.duration = duration } } public final class AnimationCacheItem { - public let numFrames: Int - private let getFrameImpl: (Int) -> AnimationCacheItemFrame? - - public init(numFrames: Int, getFrame: @escaping (Int) -> AnimationCacheItemFrame?) { - self.numFrames = numFrames - self.getFrameImpl = getFrame + public enum Advance { + case duration(Double) + case frames(Int) } - public func getFrame(index: Int) -> AnimationCacheItemFrame? { - return self.getFrameImpl(index) + public let numFrames: Int + private let advanceImpl: (Advance, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? + + public init(numFrames: Int, advanceImpl: @escaping (Advance, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?) { + self.numFrames = numFrames + self.advanceImpl = advanceImpl + } + + public func advance(advance: Advance, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { + return self.advanceImpl(advance, requestedFormat) + } +} + +public struct AnimationCacheItemDrawingSurface { + public let argb: UnsafeMutablePointer + public let width: Int + public let height: Int + public let bytesPerRow: Int + public let length: Int + + init( + argb: UnsafeMutablePointer, + width: Int, + height: Int, + bytesPerRow: Int, + length: Int + ) { + self.argb = argb + self.width = width + self.height = height + self.bytesPerRow = bytesPerRow + self.length = length } } public protocol AnimationCacheItemWriter: AnyObject { - func add(bytes: UnsafeRawPointer, length: Int, width: Int, height: Int, bytesPerRow: Int, duration: Double) + var queue: Queue { get } + var isCancelled: Bool { get } + + func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Double?, proposedWidth: Int, proposedHeight: Int) func finish() } +public final class AnimationCacheItemResult { + public let item: AnimationCacheItem? + public let isFinal: Bool + + public init(item: AnimationCacheItem?, isFinal: Bool) { + self.item = item + self.isFinal = isFinal + } +} + public protocol AnimationCache: AnyObject { - func get(sourceId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Signal - func getSynchronously(sourceId: String) -> AnimationCacheItem? + func get(sourceId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Signal + func getFirstFrameSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? + func getFirstFrame(queue: Queue, sourceId: String, size: CGSize, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable } private func md5Hash(_ string: String) -> String { @@ -56,7 +121,7 @@ private func md5Hash(_ string: String) -> String { } } -private func itemSubpath(hashString: String) -> (directory: String, fileName: String) { +private func itemSubpath(hashString: String, width: Int, height: Int) -> (directory: String, fileName: String) { assert(hashString.count == 32) var directory = "" @@ -67,71 +132,461 @@ private func itemSubpath(hashString: String) -> (directory: String, fileName: St directory.append(String(hashString[hashString.index(hashString.startIndex, offsetBy: i * 2) ..< hashString.index(hashString.startIndex, offsetBy: (i + 1) * 2)])) } - return (directory, hashString) + return (directory, "\(hashString)_\(width)x\(height)") } -private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { - private struct ParameterSet: Equatable { - var width: Int - var height: Int - var bytesPerRow: Int +private func roundUp(_ numToRound: Int, multiple: Int) -> Int { + if multiple == 0 { + return numToRound + } + + let remainder = numToRound % multiple + if remainder == 0 { + return numToRound; + } + + return numToRound + multiple - remainder +} + +private func compressData(data: Data, addSizeHeader: Bool = false) -> Data? { + let algorithm: compression_algorithm = COMPRESSION_LZFSE + + let scratchData = malloc(compression_encode_scratch_buffer_size(algorithm))! + defer { + free(scratchData) + } + + let headerSize = addSizeHeader ? 4 : 0 + var compressedData = Data(count: headerSize + data.count + 16 * 1024) + let resultSize = compressedData.withUnsafeMutableBytes { buffer -> Int in + guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { + return 0 + } + + if addSizeHeader { + var decompressedSize: UInt32 = UInt32(data.count) + memcpy(bytes, &decompressedSize, 4) + } + + return data.withUnsafeBytes { sourceBuffer -> Int in + return compression_encode_buffer(bytes.advanced(by: headerSize), buffer.count - headerSize, sourceBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), sourceBuffer.count, scratchData, algorithm) + } + } + + if resultSize <= 0 { + return nil + } + compressedData.count = headerSize + resultSize + return compressedData +} + +private func decompressData(data: Data, range: Range, decompressedSize: Int) -> Data? { + let algorithm: compression_algorithm = COMPRESSION_LZFSE + + let scratchData = malloc(compression_decode_scratch_buffer_size(algorithm))! + defer { + free(scratchData) + } + + var decompressedFrameData = Data(count: decompressedSize) + let resultSize = decompressedFrameData.withUnsafeMutableBytes { buffer -> Int in + guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { + return 0 + } + return data.withUnsafeBytes { sourceBuffer -> Int in + return compression_decode_buffer(bytes, buffer.count, sourceBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self).advanced(by: range.lowerBound), range.upperBound - range.lowerBound, scratchData, algorithm) + } + } + + if resultSize <= 0 { + return nil + } + if decompressedFrameData.count != resultSize { + decompressedFrameData.count = resultSize + } + return decompressedFrameData +} + +private final class AnimationCacheItemWriterInternal { + enum WriteError: Error { + case generic + } + + struct CompressedResult { + var path: String } private struct FrameMetadata { - var offset: Int - var length: Int var duration: Double } - private let file: ManagedFile - private let completion: (Bool) -> Void + var isCancelled: Bool = false - private var currentParameterSet: ParameterSet? + private let compressedPath: String + private let file: ManagedFile + private let compressedWriter: CompressedFileWriter + + private var currentYUVASurface: ImageYUVA420? + private var currentDctData: DctData? + private var currentDctCoefficients: DctCoefficientsYUVA420? private var contentLengthOffset: Int? private var isFailed: Bool = false private var isFinished: Bool = false private var frames: [FrameMetadata] = [] - private var contentLength: Int = 0 - private let lock = Lock() + private let dctQualityLuma: Int + private let dctQualityChroma: Int - init?(tempPath: String, completion: @escaping (Bool) -> Void) { - guard let file = ManagedFile(queue: nil, path: tempPath, mode: .readwrite) else { + init?(allocateTempFile: @escaping () -> String) { + self.dctQualityLuma = 70 + self.dctQualityChroma = 88 + + self.compressedPath = allocateTempFile() + + guard let file = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { + return nil + } + guard let compressedWriter = CompressedFileWriter(file: file) else { return nil } self.file = file + self.compressedWriter = compressedWriter + } + + func add(with drawingBlock: (ImageYUVA420) -> Double?, proposedWidth: Int, proposedHeight: Int) throws { + if self.isFailed || self.isFinished { + return + } + + guard !self.isFailed, !self.isFinished else { + return + } + + let width = roundUp(proposedWidth, multiple: 16) + let height = roundUp(proposedHeight, multiple: 16) + + var isFirstFrame = false + + let yuvaSurface: ImageYUVA420 + if let current = self.currentYUVASurface { + if current.yPlane.width == width && current.yPlane.height == height { + yuvaSurface = current + } else { + self.isFailed = true + return + } + } else { + isFirstFrame = true + yuvaSurface = ImageYUVA420(width: width, height: height, rowAlignment: nil) + self.currentYUVASurface = yuvaSurface + } + + let dctCoefficients: DctCoefficientsYUVA420 + if let current = self.currentDctCoefficients { + if current.yPlane.width == width && current.yPlane.height == height { + dctCoefficients = current + } else { + self.isFailed = true + return + } + } else { + dctCoefficients = DctCoefficientsYUVA420(width: width, height: height) + self.currentDctCoefficients = dctCoefficients + } + + let dctData: DctData + if let current = self.currentDctData { + dctData = current + } else { + dctData = DctData(generatingTablesAtQualityLuma: self.dctQualityLuma, chroma: self.dctQualityChroma) + self.currentDctData = dctData + } + + let duration = drawingBlock(yuvaSurface) + + guard let duration = duration else { + return + } + + yuvaSurface.dct(dctData: dctData, target: dctCoefficients) + + if isFirstFrame { + self.file.write(4 as UInt32) + + self.file.write(UInt32(dctCoefficients.yPlane.width)) + self.file.write(UInt32(dctCoefficients.yPlane.height)) + + let lumaDctTable = dctData.lumaTable.serializedData() + self.file.write(UInt32(lumaDctTable.count)) + let _ = self.file.write(lumaDctTable) + + let chromaDctTable = dctData.chromaTable.serializedData() + self.file.write(UInt32(chromaDctTable.count)) + let _ = self.file.write(chromaDctTable) + + self.contentLengthOffset = Int(self.file.position()) + self.file.write(0 as UInt32) + } + + let frameLength = dctCoefficients.yPlane.data.count + dctCoefficients.uPlane.data.count + dctCoefficients.vPlane.data.count + dctCoefficients.aPlane.data.count + try self.compressedWriter.writeUInt32(UInt32(frameLength)) + + for i in 0 ..< 4 { + let dctPlane: DctCoefficientPlane + switch i { + case 0: + dctPlane = dctCoefficients.yPlane + case 1: + dctPlane = dctCoefficients.uPlane + case 2: + dctPlane = dctCoefficients.vPlane + case 3: + dctPlane = dctCoefficients.aPlane + default: + preconditionFailure() + } + + try self.compressedWriter.writeUInt32(UInt32(dctPlane.data.count)) + try dctPlane.data.withUnsafeBytes { bytes in + try self.compressedWriter.write(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + } + } + + self.frames.append(FrameMetadata(duration: duration)) + } + + func finish() throws -> CompressedResult { + var shouldComplete = false + + do { + if !self.isFinished { + self.isFinished = true + shouldComplete = true + + try self.compressedWriter.flush() + + guard let contentLengthOffset = self.contentLengthOffset else { + self.isFailed = true + throw WriteError.generic + } + assert(contentLengthOffset >= 0) + + let metadataPosition = file.position() + let contentLength = Int(metadataPosition) - contentLengthOffset - 4 + file.seek(position: Int64(contentLengthOffset)) + file.write(UInt32(contentLength)) + + file.seek(position: metadataPosition) + file.write(UInt32(self.frames.count)) + for frame in self.frames { + file.write(Float32(frame.duration)) + } + + if !self.frames.isEmpty { + } else { + self.isFailed = true + throw WriteError.generic + } + + self.file._unsafeClose() + } + } catch let e { + throw e + } + + if shouldComplete { + if !self.isFailed { + return CompressedResult(path: self.compressedPath) + } else { + let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) + throw WriteError.generic + } + } else { + throw WriteError.generic + } + } +} + +private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { + struct CompressedResult { + var animationPath: String + } + + private struct FrameMetadata { + var duration: Double + } + + let queue: Queue + var isCancelled: Bool = false + + private let compressedPath: String + private var file: ManagedFile? + private var compressedWriter: CompressedFileWriter? + private let completion: (CompressedResult?) -> Void + + private var currentSurface: ImageARGB? + private var currentYUVASurface: ImageYUVA420? + private var currentDctData: DctData? + private var currentDctCoefficients: DctCoefficientsYUVA420? + private var contentLengthOffset: Int? + private var isFailed: Bool = false + private var isFinished: Bool = false + + private var frames: [FrameMetadata] = [] + + private let dctQualityLuma: Int + private let dctQualityChroma: Int + + private let lock = Lock() + + init?(queue: Queue, allocateTempFile: @escaping () -> String, completion: @escaping (CompressedResult?) -> Void) { + self.dctQualityLuma = 70 + self.dctQualityChroma = 88 + + self.queue = queue + self.compressedPath = allocateTempFile() + + guard let file = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { + return nil + } + self.file = file + self.compressedWriter = CompressedFileWriter(file: file) self.completion = completion } - func add(bytes: UnsafeRawPointer, length: Int, width: Int, height: Int, bytesPerRow: Int, duration: Double) { + func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Double?, proposedWidth: Int, proposedHeight: Int) { + if proposedWidth == 0 || proposedHeight == 0 { + self.isFailed = true + return + } + if self.isFailed || self.isFinished { + return + } + self.lock.locked { - if self.isFailed { + guard !self.isFailed, !self.isFinished, let file = self.file, let compressedWriter = self.compressedWriter else { return } - let parameterSet = ParameterSet(width: width, height: height, bytesPerRow: bytesPerRow) - if let currentParameterSet = self.currentParameterSet { - if currentParameterSet != parameterSet { + let width = roundUp(proposedWidth, multiple: 16) + let height = roundUp(proposedHeight, multiple: 16) + + var isFirstFrame = false + + let surface: ImageARGB + if let current = self.currentSurface { + if current.argbPlane.width == width && current.argbPlane.height == height { + surface = current + } else { self.isFailed = true return } } else { - self.currentParameterSet = parameterSet + isFirstFrame = true - self.file.write(1 as UInt32) - - self.file.write(UInt32(parameterSet.width)) - self.file.write(UInt32(parameterSet.height)) - self.file.write(UInt32(parameterSet.bytesPerRow)) - - self.contentLengthOffset = Int(self.file.position()) - self.file.write(0 as UInt32) + surface = ImageARGB(width: width, height: height, rowAlignment: 32) + self.currentSurface = surface } - self.frames.append(FrameMetadata(offset: Int(self.file.position()), length: length, duration: duration)) - let _ = self.file.write(bytes, count: length) - self.contentLength += length + let yuvaSurface: ImageYUVA420 + if let current = self.currentYUVASurface { + if current.yPlane.width == width && current.yPlane.height == height { + yuvaSurface = current + } else { + self.isFailed = true + return + } + } else { + yuvaSurface = ImageYUVA420(width: width, height: height, rowAlignment: nil) + self.currentYUVASurface = yuvaSurface + } + + let dctCoefficients: DctCoefficientsYUVA420 + if let current = self.currentDctCoefficients { + if current.yPlane.width == width && current.yPlane.height == height { + dctCoefficients = current + } else { + self.isFailed = true + return + } + } else { + dctCoefficients = DctCoefficientsYUVA420(width: width, height: height) + self.currentDctCoefficients = dctCoefficients + } + + let dctData: DctData + if let current = self.currentDctData { + dctData = current + } else { + dctData = DctData(generatingTablesAtQualityLuma: self.dctQualityLuma, chroma: self.dctQualityChroma) + self.currentDctData = dctData + } + + let duration = surface.argbPlane.data.withUnsafeMutableBytes { bytes -> Double? in + return drawingBlock(AnimationCacheItemDrawingSurface( + argb: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + width: width, + height: height, + bytesPerRow: surface.argbPlane.bytesPerRow, + length: bytes.count + )) + } + + guard let duration = duration else { + return + } + + surface.toYUVA420(target: yuvaSurface) + yuvaSurface.dct(dctData: dctData, target: dctCoefficients) + + if isFirstFrame { + file.write(4 as UInt32) + + file.write(UInt32(dctCoefficients.yPlane.width)) + file.write(UInt32(dctCoefficients.yPlane.height)) + + let lumaDctTable = dctData.lumaTable.serializedData() + file.write(UInt32(lumaDctTable.count)) + let _ = file.write(lumaDctTable) + + let chromaDctTable = dctData.chromaTable.serializedData() + file.write(UInt32(chromaDctTable.count)) + let _ = file.write(chromaDctTable) + + self.contentLengthOffset = Int(file.position()) + file.write(0 as UInt32) + } + + do { + let frameLength = dctCoefficients.yPlane.data.count + dctCoefficients.uPlane.data.count + dctCoefficients.vPlane.data.count + dctCoefficients.aPlane.data.count + try compressedWriter.writeUInt32(UInt32(frameLength)) + + for i in 0 ..< 4 { + let dctPlane: DctCoefficientPlane + switch i { + case 0: + dctPlane = dctCoefficients.yPlane + case 1: + dctPlane = dctCoefficients.uPlane + case 2: + dctPlane = dctCoefficients.vPlane + case 3: + dctPlane = dctCoefficients.aPlane + default: + preconditionFailure() + } + + try compressedWriter.writeUInt32(UInt32(dctPlane.data.count)) + try dctPlane.data.withUnsafeBytes { bytes in + try compressedWriter.write(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + } + } + + self.frames.append(FrameMetadata(duration: duration)) + } catch { + self.isFailed = true + } } } @@ -142,56 +597,276 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { self.isFinished = true shouldComplete = true - guard let contentLengthOffset = self.contentLengthOffset else { + guard let contentLengthOffset = self.contentLengthOffset, let file = self.file, let compressedWriter = self.compressedWriter else { self.isFailed = true return } + assert(contentLengthOffset >= 0) - let metadataPosition = self.file.position() - self.file.seek(position: Int64(contentLengthOffset)) - self.file.write(UInt32(self.contentLength)) + do { + try compressedWriter.flush() - self.file.seek(position: metadataPosition) - self.file.write(UInt32(self.frames.count)) - for frame in self.frames { - self.file.write(UInt32(frame.offset)) - self.file.write(UInt32(frame.length)) - self.file.write(Float32(frame.duration)) + let metadataPosition = file.position() + let contentLength = Int(metadataPosition) - contentLengthOffset - 4 + file.seek(position: Int64(contentLengthOffset)) + file.write(UInt32(contentLength)) + + file.seek(position: metadataPosition) + file.write(UInt32(self.frames.count)) + for frame in self.frames { + file.write(Float32(frame.duration)) + } + + if !self.isFailed { + self.compressedWriter = nil + self.file = nil + + file._unsafeClose() + } + } catch { + self.isFailed = true } } } if shouldComplete { - self.completion(!self.isFailed) + if !self.isFailed { + self.completion(CompressedResult(animationPath: self.compressedPath)) + } else { + let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) + self.completion(nil) + } } } } private final class AnimationCacheItemAccessor { + private enum ReadError: Error { + case generic + } + + final class CurrentFrame { + let index: Int + var remainingDuration: Double + let duration: Double + let dctCoefficients: DctCoefficientsYUVA420 + + init(index: Int, duration: Double, dctCoefficients: DctCoefficientsYUVA420) { + self.index = index + self.duration = duration + self.remainingDuration = duration + self.dctCoefficients = dctCoefficients + } + } + struct FrameInfo { - let range: Range let duration: Double } private let data: Data + private var compressedDataReader: DecompressedData? + private let range: Range private let frameMapping: [Int: FrameInfo] - private let format: AnimationCacheItemFrame.Format + private let width: Int + private let height: Int + private let durationMapping: [Double] - init(data: Data, frameMapping: [Int: FrameInfo], format: AnimationCacheItemFrame.Format) { + private var currentFrame: CurrentFrame? + + private var currentYUVASurface: ImageYUVA420? + private let currentDctData: DctData + private var sharedDctCoefficients: DctCoefficientsYUVA420? + + init(data: Data, range: Range, frameMapping: [FrameInfo], width: Int, height: Int, dctData: DctData) { self.data = data - self.frameMapping = frameMapping - self.format = format + self.range = range + self.width = width + self.height = height + + var resultFrameMapping: [Int: FrameInfo] = [:] + var durationMapping: [Double] = [] + + for i in 0 ..< frameMapping.count { + let frame = frameMapping[i] + resultFrameMapping[i] = frame + durationMapping.append(frame.duration) + } + + self.frameMapping = resultFrameMapping + self.durationMapping = durationMapping + + self.currentDctData = dctData } - func getFrame(index: Int) -> AnimationCacheItemFrame? { - guard let frameInfo = self.frameMapping[index] else { + private func loadNextFrame() { + let index: Int + if let currentFrame = self.currentFrame { + if currentFrame.index + 1 >= self.durationMapping.count { + index = 0 + self.compressedDataReader = nil + } else { + index = currentFrame.index + 1 + } + } else { + index = 0 + self.compressedDataReader = nil + } + + if self.compressedDataReader == nil { + self.compressedDataReader = DecompressedData(compressedData: self.data, dataRange: self.range) + } + + guard let compressedDataReader = self.compressedDataReader else { + self.currentFrame = nil + return + } + + do { + let frameLength = Int(try compressedDataReader.readUInt32()) + + let dctCoefficients: DctCoefficientsYUVA420 + if let sharedDctCoefficients = self.sharedDctCoefficients, sharedDctCoefficients.yPlane.width == self.width, sharedDctCoefficients.yPlane.height == self.height { + dctCoefficients = sharedDctCoefficients + } else { + dctCoefficients = DctCoefficientsYUVA420(width: self.width, height: self.height) + self.sharedDctCoefficients = dctCoefficients + } + + var frameOffset = 0 + for i in 0 ..< 4 { + let planeLength = Int(try compressedDataReader.readUInt32()) + if planeLength < 0 || planeLength > 20 * 1024 * 1024 { + throw ReadError.generic + } + + let plane: DctCoefficientPlane + switch i { + case 0: + plane = dctCoefficients.yPlane + case 1: + plane = dctCoefficients.uPlane + case 2: + plane = dctCoefficients.vPlane + case 3: + plane = dctCoefficients.aPlane + default: + throw ReadError.generic + } + + if planeLength != plane.data.count { + throw ReadError.generic + } + + if frameOffset + plane.data.count > frameLength { + throw ReadError.generic + } + + try plane.data.withUnsafeMutableBytes { bytes in + try compressedDataReader.read(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + } + frameOffset += plane.data.count + } + + self.currentFrame = CurrentFrame(index: index, duration: self.durationMapping[index], dctCoefficients: dctCoefficients) + } catch { + self.currentFrame = nil + self.compressedDataReader = nil + } + } + + func advance(advance: AnimationCacheItem.Advance, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { + switch advance { + case let .frames(count): + for _ in 0 ..< count { + self.loadNextFrame() + } + case let .duration(duration): + var durationOverflow = duration + while true { + if let currentFrame = self.currentFrame { + currentFrame.remainingDuration -= durationOverflow + if currentFrame.remainingDuration <= 0.0 { + durationOverflow = -currentFrame.remainingDuration + self.loadNextFrame() + } else { + break + } + } else { + self.loadNextFrame() + break + } + } + } + + guard let currentFrame = self.currentFrame else { return nil } - return AnimationCacheItemFrame(data: data, range: frameInfo.range, format: self.format, duration: frameInfo.duration) + let yuvaSurface: ImageYUVA420 + switch requestedFormat { + case .rgba: + if let currentYUVASurface = self.currentYUVASurface { + yuvaSurface = currentYUVASurface + } else { + yuvaSurface = ImageYUVA420(width: currentFrame.dctCoefficients.yPlane.width, height: currentFrame.dctCoefficients.yPlane.height, rowAlignment: nil) + } + case let .yuva(preferredRowAlignment): + yuvaSurface = ImageYUVA420(width: currentFrame.dctCoefficients.yPlane.width, height: currentFrame.dctCoefficients.yPlane.height, rowAlignment: preferredRowAlignment) + } + + currentFrame.dctCoefficients.idct(dctData: self.currentDctData, target: yuvaSurface) + + switch requestedFormat { + case .rgba: + let currentSurface = ImageARGB(width: yuvaSurface.yPlane.width, height: yuvaSurface.yPlane.height, rowAlignment: 32) + yuvaSurface.toARGB(target: currentSurface) + self.currentYUVASurface = yuvaSurface + + return AnimationCacheItemFrame(format: .rgba(data: currentSurface.argbPlane.data, width: currentSurface.argbPlane.width, height: currentSurface.argbPlane.height, bytesPerRow: currentSurface.argbPlane.bytesPerRow), duration: currentFrame.duration) + case .yuva: + return AnimationCacheItemFrame( + format: .yuva( + y: AnimationCacheItemFrame.Plane( + data: yuvaSurface.yPlane.data, + width: yuvaSurface.yPlane.width, + height: yuvaSurface.yPlane.height, + bytesPerRow: yuvaSurface.yPlane.bytesPerRow + ), + u: AnimationCacheItemFrame.Plane( + data: yuvaSurface.uPlane.data, + width: yuvaSurface.uPlane.width, + height: yuvaSurface.uPlane.height, + bytesPerRow: yuvaSurface.uPlane.bytesPerRow + ), + v: AnimationCacheItemFrame.Plane( + data: yuvaSurface.vPlane.data, + width: yuvaSurface.vPlane.width, + height: yuvaSurface.vPlane.height, + bytesPerRow: yuvaSurface.vPlane.bytesPerRow + ), + a: AnimationCacheItemFrame.Plane( + data: yuvaSurface.aPlane.data, + width: yuvaSurface.aPlane.width, + height: yuvaSurface.aPlane.height, + bytesPerRow: yuvaSurface.aPlane.bytesPerRow + ) + ), + duration: currentFrame.duration + ) + } } } +private func readData(data: Data, offset: Int, count: Int) -> Data { + var result = Data(count: count) + result.withUnsafeMutableBytes { bytes -> Void in + data.withUnsafeBytes { dataBytes -> Void in + memcpy(bytes.baseAddress!, dataBytes.baseAddress!.advanced(by: offset), count) + } + } + return result +} + private func readUInt32(data: Data, offset: Int) -> UInt32 { var value: UInt32 = 0 withUnsafeMutableBytes(of: &value, { bytes -> Void in @@ -203,82 +878,448 @@ private func readUInt32(data: Data, offset: Int) -> UInt32 { return value } -private func loadItem(path: String) -> AnimationCacheItem? { - guard let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) else { - return nil - } - let dataLength = data.count +private func readFloat32(data: Data, offset: Int) -> Float32 { + var value: Float32 = 0 + withUnsafeMutableBytes(of: &value, { bytes -> Void in + data.withUnsafeBytes { dataBytes -> Void in + memcpy(bytes.baseAddress!, dataBytes.baseAddress!.advanced(by: offset), 4) + } + }) - var offset = 0 - - guard dataLength >= offset + 4 else { - return nil - } - let formatVersion = readUInt32(data: data, offset: offset) - offset += 4 - if formatVersion != 1 { - return nil + return value +} + +private func writeUInt32(data: inout Data, value: UInt32) { + var value: UInt32 = value + withUnsafeBytes(of: &value, { bytes -> Void in + data.count += 4 + data.withUnsafeMutableBytes { dataBytes -> Void in + memcpy(dataBytes.baseAddress!.advanced(by: dataBytes.count - 4), bytes.baseAddress!, 4) + } + }) +} + +private func writeFloat32(data: inout Data, value: Float32) { + var value: Float32 = value + withUnsafeBytes(of: &value, { bytes -> Void in + data.count += 4 + data.withUnsafeMutableBytes { dataBytes -> Void in + memcpy(dataBytes.baseAddress!.advanced(by: dataBytes.count - 4), bytes.baseAddress!, 4) + } + }) +} + +private final class CompressedFileWriter { + enum WriteError: Error { + case generic } - guard dataLength >= offset + 4 else { - return nil - } - let width = readUInt32(data: data, offset: offset) - offset += 4 + private let file: ManagedFile + private let stream: UnsafeMutablePointer - guard dataLength >= offset + 4 else { - return nil - } - let height = readUInt32(data: data, offset: offset) - offset += 4 + private let tempBufferSize: Int = 32 * 1024 + private let tempBuffer: UnsafeMutablePointer - guard dataLength >= offset + 4 else { - return nil - } - let bytesPerRow = readUInt32(data: data, offset: offset) - offset += 4 + private var didFail: Bool = false - guard dataLength >= offset + 4 else { - return nil - } - let frameDataLength = readUInt32(data: data, offset: offset) - offset += 4 - - offset += Int(frameDataLength) - - guard dataLength >= offset + 4 else { - return nil - } - let numFrames = readUInt32(data: data, offset: offset) - offset += 4 - - var frameMapping: [Int: AnimationCacheItemAccessor.FrameInfo] = [:] - for i in 0 ..< Int(numFrames) { - guard dataLength >= offset + 4 + 4 + 4 else { + init?(file: ManagedFile) { + self.file = file + + self.stream = UnsafeMutablePointer.allocate(capacity: 1) + guard compression_stream_init(self.stream, COMPRESSION_STREAM_ENCODE, COMPRESSION_LZFSE) != COMPRESSION_STATUS_ERROR else { + self.stream.deallocate() return nil } - let frameStart = readUInt32(data: data, offset: offset) - offset += 4 - let frameLength = readUInt32(data: data, offset: offset) - offset += 4 - let frameDuration = readUInt32(data: data, offset: offset) - offset += 4 - - frameMapping[i] = AnimationCacheItemAccessor.FrameInfo(range: Int(frameStart) ..< Int(frameStart + frameLength), duration: Double(frameDuration)) + self.tempBuffer = UnsafeMutablePointer.allocate(capacity: self.tempBufferSize) } - let itemAccessor = AnimationCacheItemAccessor(data: data, frameMapping: frameMapping, format: .rgba(width: Int(width), height: Int(height), bytesPerRow: Int(bytesPerRow))) + deinit { + compression_stream_destroy(self.stream) + self.stream.deallocate() + self.tempBuffer.deallocate() + } - return AnimationCacheItem(numFrames: Int(numFrames), getFrame: { index in - return itemAccessor.getFrame(index: index) + func write(bytes: UnsafePointer, count: Int) throws { + if self.didFail { + throw WriteError.generic + } + + self.stream.pointee.src_ptr = bytes + self.stream.pointee.src_size = count + + while true { + self.stream.pointee.dst_ptr = self.tempBuffer + self.stream.pointee.dst_size = self.tempBufferSize + + let status = compression_stream_process(self.stream, 0) + if status == COMPRESSION_STATUS_ERROR { + self.didFail = true + throw WriteError.generic + } + + let writtenBytes = self.tempBufferSize - self.stream.pointee.dst_size + if writtenBytes > 0 { + let _ = self.file.write(self.tempBuffer, count: writtenBytes) + } + + if status == COMPRESSION_STATUS_END { + break + } else { + if self.stream.pointee.src_size == 0 { + break + } + } + } + } + + func flush() throws { + if self.didFail { + throw WriteError.generic + } + + while true { + self.stream.pointee.dst_ptr = self.tempBuffer + self.stream.pointee.dst_size = self.tempBufferSize + + let status = compression_stream_process(self.stream, Int32(COMPRESSION_STREAM_FINALIZE.rawValue)) + if status == COMPRESSION_STATUS_ERROR { + self.didFail = true + throw WriteError.generic + } + + let writtenBytes = self.tempBufferSize - self.stream.pointee.dst_size + if writtenBytes > 0 { + let _ = self.file.write(self.tempBuffer, count: writtenBytes) + } + + if status == COMPRESSION_STATUS_END { + break + } + } + } + + func writeUInt32(_ value: UInt32) throws { + var value: UInt32 = value + try withUnsafeBytes(of: &value, { bytes -> Void in + try self.write(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: 4) + }) + } + + func writeFloat32(_ value: Float32) throws { + var value: Float32 = value + try withUnsafeBytes(of: &value, { bytes -> Void in + try self.write(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: 4) + }) + } +} + +private final class DecompressedData { + enum ReadError: Error { + case didReadToEnd + } + + private let compressedData: Data + private let dataRange: Range + private let stream: UnsafeMutablePointer + private var isComplete = false + + init?(compressedData: Data, dataRange: Range) { + self.compressedData = compressedData + self.dataRange = dataRange + + self.stream = UnsafeMutablePointer.allocate(capacity: 1) + guard compression_stream_init(self.stream, COMPRESSION_STREAM_DECODE, COMPRESSION_LZFSE) != COMPRESSION_STATUS_ERROR else { + self.stream.deallocate() + return nil + } + + self.compressedData.withUnsafeBytes { bytes in + self.stream.pointee.src_ptr = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self).advanced(by: dataRange.lowerBound) + self.stream.pointee.src_size = dataRange.upperBound - dataRange.lowerBound + } + } + + deinit { + compression_stream_destroy(self.stream) + self.stream.deallocate() + } + + func read(bytes: UnsafeMutablePointer, count: Int) throws { + if self.isComplete { + throw ReadError.didReadToEnd + } + + self.stream.pointee.dst_ptr = bytes + self.stream.pointee.dst_size = count + + let status = compression_stream_process(self.stream, 0) + + if status == COMPRESSION_STATUS_ERROR { + self.isComplete = true + throw ReadError.didReadToEnd + } else if status == COMPRESSION_STATUS_END { + if self.stream.pointee.src_size == 0 { + self.isComplete = true + } + } + + if self.stream.pointee.dst_size != 0 { + throw ReadError.didReadToEnd + } + } + + func readUInt32() throws -> UInt32 { + var value: UInt32 = 0 + try withUnsafeMutableBytes(of: &value, { bytes -> Void in + try self.read(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: 4) + }) + return value + } + + func readFloat32() throws -> Float32 { + var value: Float32 = 0 + try withUnsafeMutableBytes(of: &value, { bytes -> Void in + try self.read(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: 4) + }) + return value + } +} + +private enum LoadItemError: Error { + case dataError +} + +private func loadItem(path: String) throws -> AnimationCacheItem { + guard let compressedData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) else { + throw LoadItemError.dataError + } + + var offset: Int = 0 + let dataLength = compressedData.count + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let formatVersion = readUInt32(data: compressedData, offset: offset) + offset += 4 + if formatVersion != 4 { + throw LoadItemError.dataError + } + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let width = readUInt32(data: compressedData, offset: offset) + offset += 4 + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let height = readUInt32(data: compressedData, offset: offset) + offset += 4 + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let dctLumaTableLength = readUInt32(data: compressedData, offset: offset) + offset += 4 + + if offset + Int(dctLumaTableLength) > dataLength { + throw LoadItemError.dataError + } + let dctLumaData = readData(data: compressedData, offset: offset, count: Int(dctLumaTableLength)) + offset += Int(dctLumaTableLength) + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let dctChromaTableLength = readUInt32(data: compressedData, offset: offset) + offset += 4 + + if offset + Int(dctChromaTableLength) > dataLength { + throw LoadItemError.dataError + } + let dctChromaData = readData(data: compressedData, offset: offset, count: Int(dctChromaTableLength)) + offset += Int(dctChromaTableLength) + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let contentLength = Int(readUInt32(data: compressedData, offset: offset)) + offset += 4 + + let compressedFrameDataRange = offset ..< (offset + contentLength) + offset += contentLength + + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let frameCount = Int(readUInt32(data: compressedData, offset: offset)) + offset += 4 + + var frameMapping: [AnimationCacheItemAccessor.FrameInfo] = [] + for _ in 0 ..< frameCount { + if offset + 4 > dataLength { + throw LoadItemError.dataError + } + let frameDuration = readFloat32(data: compressedData, offset: offset) + offset += 4 + + frameMapping.append(AnimationCacheItemAccessor.FrameInfo(duration: Double(frameDuration))) + } + + guard let dctData = DctData(lumaTable: dctLumaData, chromaTable: dctChromaData) else { + throw LoadItemError.dataError + } + + let itemAccessor = AnimationCacheItemAccessor(data: compressedData, range: compressedFrameDataRange, frameMapping: frameMapping, width: Int(width), height: Int(height), dctData: dctData) + + return AnimationCacheItem(numFrames: frameMapping.count, advanceImpl: { advance, requestedFormat in + return itemAccessor.advance(advance: advance, requestedFormat: requestedFormat) }) } +private func adaptItemFromHigherResolution(itemPath: String, width: Int, height: Int, itemDirectoryPath: String, higherResolutionPath: String, allocateTempFile: @escaping () -> String) -> AnimationCacheItem? { + guard let higherResolutionItem = try? loadItem(path: higherResolutionPath) else { + return nil + } + guard let writer = AnimationCacheItemWriterInternal(allocateTempFile: allocateTempFile) else { + return nil + } + + do { + for _ in 0 ..< higherResolutionItem.numFrames { + try writer.add(with: { yuva in + guard let frame = higherResolutionItem.advance(advance: .frames(1), requestedFormat: .yuva(rowAlignment: yuva.yPlane.rowAlignment)) else { + return nil + } + switch frame.format { + case .rgba: + return nil + case let .yuva(y, u, v, a): + yuva.yPlane.copyScaled(fromPlane: y) + yuva.uPlane.copyScaled(fromPlane: u) + yuva.vPlane.copyScaled(fromPlane: v) + yuva.aPlane.copyScaled(fromPlane: a) + } + + return frame.duration + }, proposedWidth: width, proposedHeight: height) + } + + let result = try writer.finish() + + guard let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: itemDirectoryPath), withIntermediateDirectories: true, attributes: nil) else { + return nil + } + let _ = try? FileManager.default.removeItem(atPath: itemPath) + guard let _ = try? FileManager.default.moveItem(atPath: result.path, toPath: itemPath) else { + return nil + } + guard let item = try? loadItem(path: itemPath) else { + return nil + } + return item + } catch { + return nil + } +} + +private func generateFirstFrameFromItem(itemPath: String, animationItemPath: String, allocateTempFile: @escaping () -> String) -> Bool { + guard let animationItem = try? loadItem(path: animationItemPath) else { + return false + } + guard let writer = AnimationCacheItemWriterInternal(allocateTempFile: allocateTempFile) else { + return false + } + + do { + for _ in 0 ..< min(1, animationItem.numFrames) { + guard let frame = animationItem.advance(advance: .frames(1), requestedFormat: .yuva(rowAlignment: 1)) else { + return false + } + switch frame.format { + case .rgba: + return false + case let .yuva(y, u, v, a): + try writer.add(with: { yuva in + assert(yuva.yPlane.bytesPerRow == y.bytesPerRow) + assert(yuva.uPlane.bytesPerRow == u.bytesPerRow) + assert(yuva.vPlane.bytesPerRow == v.bytesPerRow) + assert(yuva.aPlane.bytesPerRow == a.bytesPerRow) + + yuva.yPlane.copyScaled(fromPlane: y) + yuva.uPlane.copyScaled(fromPlane: u) + yuva.vPlane.copyScaled(fromPlane: v) + yuva.aPlane.copyScaled(fromPlane: a) + + return frame.duration + }, proposedWidth: y.width, proposedHeight: y.height) + } + } + + let result = try writer.finish() + + let _ = try? FileManager.default.removeItem(atPath: itemPath) + guard let _ = try? FileManager.default.moveItem(atPath: result.path, toPath: itemPath) else { + return false + } + return true + } catch { + return false + } +} + +private func findHigherResolutionFileForAdaptation(itemDirectoryPath: String, baseName: String, baseSuffix: String, width: Int, height: Int) -> String? { + var candidates: [(path: String, width: Int, height: Int)] = [] + if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: itemDirectoryPath), includingPropertiesForKeys: nil, options: .skipsSubdirectoryDescendants, errorHandler: nil) { + for url in enumerator { + guard let url = url as? URL else { + continue + } + let fileName = url.lastPathComponent + if fileName.hasPrefix(baseName) { + let scanner = Scanner(string: fileName) + guard scanner.scanString(baseName, into: nil) else { + continue + } + var itemWidth: Int = 0 + guard scanner.scanInt(&itemWidth) else { + continue + } + guard scanner.scanString("x", into: nil) else { + continue + } + var itemHeight: Int = 0 + guard scanner.scanInt(&itemHeight) else { + continue + } + if !baseSuffix.isEmpty { + guard scanner.scanString(baseSuffix, into: nil) else { + continue + } + } + guard scanner.isAtEnd else { + continue + } + if itemWidth > width && itemHeight > height { + candidates.append((url.path, itemWidth, itemHeight)) + } + } + } + } + if !candidates.isEmpty { + candidates.sort(by: { $0.width < $1.width }) + return candidates[0].path + } + return nil +} + public final class AnimationCacheImpl: AnimationCache { private final class Impl { private final class ItemContext { - let subscribers = Bag<(AnimationCacheItem?) -> Void>() + let subscribers = Bag<(AnimationCacheItemResult) -> Void>() let disposable = MetaDisposable() deinit { @@ -290,10 +1331,22 @@ public final class AnimationCacheImpl: AnimationCache { private let basePath: String private let allocateTempFile: () -> String + private let fetchQueues: [Queue] + private var nextFetchQueueIndex: Int = 0 + private var itemContexts: [String: ItemContext] = [:] init(queue: Queue, basePath: String, allocateTempFile: @escaping () -> String) { self.queue = queue + + let fetchQueueCount: Int + if ProcessInfo.processInfo.processorCount > 2 { + fetchQueueCount = 3 + } else { + fetchQueueCount = 2 + } + + self.fetchQueues = (0 ..< fetchQueueCount).map { i in Queue(name: "AnimationCacheImpl-Fetch\(i)", qos: .default) } self.basePath = basePath self.allocateTempFile = allocateTempFile } @@ -301,13 +1354,14 @@ public final class AnimationCacheImpl: AnimationCache { deinit { } - func get(sourceId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId)) + func get(sourceId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, updateResult: @escaping (AnimationCacheItemResult) -> Void) -> Disposable { + let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId), width: Int(size.width), height: Int(size.height)) let itemDirectoryPath = "\(self.basePath)/\(sourceIdPath.directory)" let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" + let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" - if FileManager.default.fileExists(atPath: itemPath) { - completion(loadItem(path: itemPath)) + if FileManager.default.fileExists(atPath: itemPath), let item = try? loadItem(path: itemPath) { + updateResult(AnimationCacheItemResult(item: item, isFinal: true)) return EmptyDisposable } @@ -323,11 +1377,15 @@ public final class AnimationCacheImpl: AnimationCache { } let queue = self.queue - let index = itemContext.subscribers.add(completion) + let index = itemContext.subscribers.add(updateResult) + + updateResult(AnimationCacheItemResult(item: nil, isFinal: false)) if beginFetch { - let tempPath = self.allocateTempFile() - guard let writer = AnimationCacheItemWriterImpl(tempPath: tempPath, completion: { [weak self, weak itemContext] success in + let fetchQueueIndex = self.nextFetchQueueIndex + self.nextFetchQueueIndex += 1 + let allocateTempFile = self.allocateTempFile + guard let writer = AnimationCacheItemWriterImpl(queue: self.fetchQueues[fetchQueueIndex % self.fetchQueues.count], allocateTempFile: self.allocateTempFile, completion: { [weak self, weak itemContext] result in queue.async { guard let strongSelf = self, let itemContext = itemContext, itemContext === strongSelf.itemContexts[sourceId] else { return @@ -335,30 +1393,39 @@ public final class AnimationCacheImpl: AnimationCache { strongSelf.itemContexts.removeValue(forKey: sourceId) - guard success else { + guard let result = result else { return } guard let _ = try? FileManager.default.createDirectory(at: URL(fileURLWithPath: itemDirectoryPath), withIntermediateDirectories: true, attributes: nil) else { return } - guard let _ = try? FileManager.default.moveItem(atPath: tempPath, toPath: itemPath) else { + let _ = try? FileManager.default.removeItem(atPath: itemPath) + guard let _ = try? FileManager.default.moveItem(atPath: result.animationPath, toPath: itemPath) else { return } - guard let item = loadItem(path: itemPath) else { + + let _ = generateFirstFrameFromItem(itemPath: itemFirstFramePath, animationItemPath: itemPath, allocateTempFile: allocateTempFile) + + guard let item = try? loadItem(path: itemPath) else { return } for f in itemContext.subscribers.copyItems() { - f(item) + f(AnimationCacheItemResult(item: item, isFinal: true)) } } }) else { return EmptyDisposable } - let fetchDisposable = fetch(writer) + let fetchDisposable = MetaDisposable() + fetchDisposable.set(fetch(size, writer)) - itemContext.disposable.set(ActionDisposable { + itemContext.disposable.set(ActionDisposable { [weak writer] in + if let writer = writer { + writer.isCancelled = true + } + fetchDisposable.dispose() }) } @@ -377,38 +1444,75 @@ public final class AnimationCacheImpl: AnimationCache { } } - func getSynchronously(sourceId: String) -> AnimationCacheItem? { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId)) - let itemDirectoryPath = "\(self.basePath)/\(sourceIdPath.directory)" - let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" + static func getFirstFrameSynchronously(basePath: String, sourceId: String, size: CGSize, allocateTempFile: @escaping () -> String) -> AnimationCacheItem? { + let hashString = md5Hash(sourceId) + let sourceIdPath = itemSubpath(hashString: hashString, width: Int(size.width), height: Int(size.height)) + let itemDirectoryPath = "\(basePath)/\(sourceIdPath.directory)" + let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" - if FileManager.default.fileExists(atPath: itemPath) { - return loadItem(path: itemPath) - } else { - return nil + if FileManager.default.fileExists(atPath: itemFirstFramePath) { + if let item = try? loadItem(path: itemFirstFramePath) { + return item + } } + + if let adaptationItemPath = findHigherResolutionFileForAdaptation(itemDirectoryPath: itemDirectoryPath, baseName: "\(hashString)_", baseSuffix: "-f", width: Int(size.width), height: Int(size.height)) { + if let adaptedItem = adaptItemFromHigherResolution(itemPath: itemFirstFramePath, width: Int(size.width), height: Int(size.height), itemDirectoryPath: itemDirectoryPath, higherResolutionPath: adaptationItemPath, allocateTempFile: allocateTempFile) { + return adaptedItem + } + } + + return nil + } + + static func getFirstFrame(basePath: String, sourceId: String, size: CGSize, allocateTempFile: @escaping () -> String, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { + let hashString = md5Hash(sourceId) + let sourceIdPath = itemSubpath(hashString: hashString, width: Int(size.width), height: Int(size.height)) + let itemDirectoryPath = "\(basePath)/\(sourceIdPath.directory)" + let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" + + if FileManager.default.fileExists(atPath: itemFirstFramePath), let item = try? loadItem(path: itemFirstFramePath) { + completion(item) + return EmptyDisposable + } + + if let adaptationItemPath = findHigherResolutionFileForAdaptation(itemDirectoryPath: itemDirectoryPath, baseName: "\(hashString)_", baseSuffix: "-f", width: Int(size.width), height: Int(size.height)) { + if let adaptedItem = adaptItemFromHigherResolution(itemPath: itemFirstFramePath, width: Int(size.width), height: Int(size.height), itemDirectoryPath: itemDirectoryPath, higherResolutionPath: adaptationItemPath, allocateTempFile: allocateTempFile) { + completion(adaptedItem) + return EmptyDisposable + } + } + + completion(nil) + return EmptyDisposable } } private let queue: Queue + private let basePath: String private let impl: QueueLocalObject + private let allocateTempFile: () -> String public init(basePath: String, allocateTempFile: @escaping () -> String) { let queue = Queue() self.queue = queue + self.basePath = basePath + self.allocateTempFile = allocateTempFile self.impl = QueueLocalObject(queue: queue, generate: { return Impl(queue: queue, basePath: basePath, allocateTempFile: allocateTempFile) }) } - public func get(sourceId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Signal { + public func get(sourceId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Signal { return Signal { subscriber in let disposable = MetaDisposable() self.impl.with { impl in - disposable.set(impl.get(sourceId: sourceId, fetch: fetch, completion: { result in + disposable.set(impl.get(sourceId: sourceId, size: size, fetch: fetch, updateResult: { result in subscriber.putNext(result) - subscriber.putCompletion() + if result.isFinal { + subscriber.putCompletion() + } })) } @@ -417,9 +1521,19 @@ public final class AnimationCacheImpl: AnimationCache { |> runOn(self.queue) } - public func getSynchronously(sourceId: String) -> AnimationCacheItem? { - return self.impl.syncWith { impl -> AnimationCacheItem? in - return impl.getSynchronously(sourceId: sourceId) + public func getFirstFrameSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { + return Impl.getFirstFrameSynchronously(basePath: self.basePath, sourceId: sourceId, size: size, allocateTempFile: self.allocateTempFile) + } + + public func getFirstFrame(queue: Queue, sourceId: String, size: CGSize, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { + let disposable = MetaDisposable() + + let basePath = self.basePath + let allocateTempFile = self.allocateTempFile + queue.async { + disposable.set(Impl.getFirstFrame(basePath: basePath, sourceId: sourceId, size: size, allocateTempFile: allocateTempFile, completion: completion)) } + + return disposable } } diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift new file mode 100644 index 0000000000..a0caff07c1 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -0,0 +1,281 @@ +import Foundation +import UIKit +import ImageDCT + +private func alignUp(size: Int, align: Int) -> Int { + precondition(((align - 1) & align) == 0, "Align must be a power of two") + + let alignmentMask = align - 1 + return (size + alignmentMask) & ~alignmentMask +} + +final class ImagePlane { + let width: Int + let height: Int + let bytesPerRow: Int + let rowAlignment: Int + let components: Int + var data: Data + + init(width: Int, height: Int, components: Int, rowAlignment: Int?) { + self.width = width + self.height = height + self.rowAlignment = rowAlignment ?? 1 + self.bytesPerRow = alignUp(size: width * components, align: self.rowAlignment) + self.components = components + self.data = Data(count: self.bytesPerRow * height) + } +} + +extension ImagePlane { + func copyScaled(fromPlane plane: AnimationCacheItemFrame.Plane) { + self.data.withUnsafeMutableBytes { destBytes in + plane.data.withUnsafeBytes { srcBytes in + scaleImagePlane(destBytes.baseAddress!.assumingMemoryBound(to: UInt8.self), Int32(self.width), Int32(self.height), Int32(self.bytesPerRow), srcBytes.baseAddress!.assumingMemoryBound(to: UInt8.self), Int32(plane.width), Int32(plane.height), Int32(plane.bytesPerRow)) + } + } + } +} + +final class ImageARGB { + let argbPlane: ImagePlane + + init(width: Int, height: Int, rowAlignment: Int?) { + self.argbPlane = ImagePlane(width: width, height: height, components: 4, rowAlignment: rowAlignment) + } +} + +final class ImageYUVA420 { + let yPlane: ImagePlane + let uPlane: ImagePlane + let vPlane: ImagePlane + let aPlane: ImagePlane + + init(width: Int, height: Int, rowAlignment: Int?) { + self.yPlane = ImagePlane(width: width, height: height, components: 1, rowAlignment: rowAlignment) + self.uPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, rowAlignment: rowAlignment) + self.vPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, rowAlignment: rowAlignment) + self.aPlane = ImagePlane(width: width, height: height, components: 1, rowAlignment: rowAlignment) + } +} + +final class DctCoefficientPlane { + let width: Int + let height: Int + var data: Data + + init(width: Int, height: Int) { + self.width = width + self.height = height + self.data = Data(count: width * 2 * height) + } +} + +final class DctCoefficientsYUVA420 { + let yPlane: DctCoefficientPlane + let uPlane: DctCoefficientPlane + let vPlane: DctCoefficientPlane + let aPlane: DctCoefficientPlane + + init(width: Int, height: Int) { + self.yPlane = DctCoefficientPlane(width: width, height: height) + self.uPlane = DctCoefficientPlane(width: width / 2, height: height / 2) + self.vPlane = DctCoefficientPlane(width: width / 2, height: height / 2) + self.aPlane = DctCoefficientPlane(width: width, height: height) + } +} + +extension ImageARGB { + func toYUVA420(target: ImageYUVA420) { + precondition(self.argbPlane.width == target.yPlane.width && self.argbPlane.height == target.yPlane.height) + + self.argbPlane.data.withUnsafeBytes { argbBuffer -> Void in + target.yPlane.data.withUnsafeMutableBytes { yBuffer -> Void in + target.uPlane.data.withUnsafeMutableBytes { uBuffer -> Void in + target.vPlane.data.withUnsafeMutableBytes { vBuffer -> Void in + target.aPlane.data.withUnsafeMutableBytes { aBuffer -> Void in + splitRGBAIntoYUVAPlanes( + argbBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + yBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + uBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + vBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + aBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + Int32(self.argbPlane.width), + Int32(self.argbPlane.height), + Int32(self.argbPlane.bytesPerRow) + ) + } + } + } + } + } + } + + func toYUVA420(rowAlignment: Int?) -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.argbPlane.width, height: self.argbPlane.height, rowAlignment: rowAlignment) + self.toYUVA420(target: resultImage) + return resultImage + } +} + +extension ImageYUVA420 { + func toARGB(target: ImageARGB) { + precondition(self.yPlane.width == target.argbPlane.width && self.yPlane.height == target.argbPlane.height) + + self.yPlane.data.withUnsafeBytes { yBuffer -> Void in + self.uPlane.data.withUnsafeBytes { uBuffer -> Void in + self.vPlane.data.withUnsafeBytes { vBuffer -> Void in + self.aPlane.data.withUnsafeBytes { aBuffer -> Void in + target.argbPlane.data.withUnsafeMutableBytes { argbBuffer -> Void in + combineYUVAPlanesIntoARBB( + argbBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + yBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + uBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + vBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + aBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), + Int32(target.argbPlane.width), + Int32(target.argbPlane.height), + Int32(target.argbPlane.bytesPerRow) + ) + } + } + } + } + } + } + + func toARGB(rowAlignment: Int?) -> ImageARGB { + let resultImage = ImageARGB(width: self.yPlane.width, height: self.yPlane.height, rowAlignment: rowAlignment) + self.toARGB(target: resultImage) + return resultImage + } +} + +final class DctData { + let lumaTable: ImageDCTTable + let lumaDct: ImageDCT + + let chromaTable: ImageDCTTable + let chromaDct: ImageDCT + + init?(lumaTable: Data, chromaTable: Data) { + guard let lumaTableData = ImageDCTTable(data: lumaTable) else { + return nil + } + guard let chromaTableData = ImageDCTTable(data: chromaTable) else { + return nil + } + + self.lumaTable = lumaTableData + self.lumaDct = ImageDCT(table: lumaTableData) + + self.chromaTable = chromaTableData + self.chromaDct = ImageDCT(table: chromaTableData) + } + + init(generatingTablesAtQualityLuma lumaQuality: Int, chroma chromaQuality: Int) { + self.lumaTable = ImageDCTTable(quality: lumaQuality, isChroma: false) + self.lumaDct = ImageDCT(table: self.lumaTable) + + self.chromaTable = ImageDCTTable(quality: chromaQuality, isChroma: true) + self.chromaDct = ImageDCT(table: self.chromaTable) + } +} + +extension ImageYUVA420 { + func dct(dctData: DctData, target: DctCoefficientsYUVA420) { + precondition(self.yPlane.width == target.yPlane.width && self.yPlane.height == target.yPlane.height) + + for i in 0 ..< 4 { + let sourcePlane: ImagePlane + let targetPlane: DctCoefficientPlane + let isChroma: Bool + switch i { + case 0: + sourcePlane = self.yPlane + targetPlane = target.yPlane + isChroma = false + case 1: + sourcePlane = self.uPlane + targetPlane = target.uPlane + isChroma = true + case 2: + sourcePlane = self.vPlane + targetPlane = target.vPlane + isChroma = true + case 3: + sourcePlane = self.aPlane + targetPlane = target.aPlane + isChroma = false + default: + preconditionFailure() + } + + sourcePlane.data.withUnsafeBytes { sourceBytes in + let sourcePixels = sourceBytes.baseAddress!.assumingMemoryBound(to: UInt8.self) + + targetPlane.data.withUnsafeMutableBytes { bytes in + let coefficients = bytes.baseAddress!.assumingMemoryBound(to: Int16.self) + + let dct = isChroma ? dctData.chromaDct : dctData.lumaDct + dct.forward(withPixels: sourcePixels, coefficients: coefficients, width: sourcePlane.width, height: sourcePlane.height, bytesPerRow: sourcePlane.bytesPerRow) + } + } + } + } + + func dct(dctData: DctData) -> DctCoefficientsYUVA420 { + let results = DctCoefficientsYUVA420(width: self.yPlane.width, height: self.yPlane.height) + self.dct(dctData: dctData, target: results) + return results + } +} + +extension DctCoefficientsYUVA420 { + func idct(dctData: DctData, target: ImageYUVA420) { + precondition(self.yPlane.width == target.yPlane.width && self.yPlane.height == target.yPlane.height) + + for i in 0 ..< 4 { + let sourcePlane: DctCoefficientPlane + let targetPlane: ImagePlane + let isChroma: Bool + switch i { + case 0: + sourcePlane = self.yPlane + targetPlane = target.yPlane + isChroma = false + case 1: + sourcePlane = self.uPlane + targetPlane = target.uPlane + isChroma = true + case 2: + sourcePlane = self.vPlane + targetPlane = target.vPlane + isChroma = true + case 3: + sourcePlane = self.aPlane + targetPlane = target.aPlane + isChroma = false + default: + preconditionFailure() + } + + sourcePlane.data.withUnsafeBytes { sourceBytes in + let coefficients = sourceBytes.baseAddress!.assumingMemoryBound(to: Int16.self) + + targetPlane.data.withUnsafeMutableBytes { bytes in + let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) + + let dct = isChroma ? dctData.chromaDct : dctData.lumaDct + dct.inverse(withCoefficients: coefficients, pixels: pixels, width: sourcePlane.width, height: sourcePlane.height, coefficientsPerRow: targetPlane.width, bytesPerRow: targetPlane.bytesPerRow) + } + } + } + } + + func idct(dctData: DctData, rowAlignment: Int?) -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.yPlane.width, height: self.yPlane.height, rowAlignment: rowAlignment) + self.idct(dctData: dctData, target: resultImage) + return resultImage + } +} diff --git a/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift b/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift index 800d67a95d..d4cf07ff4e 100644 --- a/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift +++ b/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift @@ -48,7 +48,6 @@ public final class AudioTranscriptionButtonComponent: Component { override init(frame: CGRect) { self.backgroundLayer = SimpleLayer() self.animationView = ComponentHostView() - self.animationView.isUserInteractionEnabled = false super.init(frame: frame) @@ -56,6 +55,8 @@ public final class AudioTranscriptionButtonComponent: Component { self.backgroundLayer.cornerRadius = 10.0 self.layer.addSublayer(self.backgroundLayer) + self.animationView.isUserInteractionEnabled = false + self.addSubview(self.animationView) self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside) @@ -109,18 +110,18 @@ public final class AudioTranscriptionButtonComponent: Component { component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: animationName, - colors: [ - "icon.Group 3.Stroke 1": foregroundColor, - "icon.Group 1.Stroke 1": foregroundColor, - "icon.Group 4.Stroke 1": foregroundColor, - "icon.Group 2.Stroke 1": foregroundColor, - "Artboard Copy 2 Outlines.Group 5.Stroke 1": foregroundColor, - "Artboard Copy 2 Outlines.Group 1.Stroke 1": foregroundColor, - "Artboard Copy 2 Outlines.Group 4.Stroke 1": foregroundColor, - "Artboard Copy Outlines.Group 1.Stroke 1": foregroundColor, - ], mode: .animateTransitionFromPrevious ), + colors: [ + "icon.Group 3.Stroke 1": foregroundColor, + "icon.Group 1.Stroke 1": foregroundColor, + "icon.Group 4.Stroke 1": foregroundColor, + "icon.Group 2.Stroke 1": foregroundColor, + "Artboard Copy 2 Outlines.Group 5.Stroke 1": foregroundColor, + "Artboard Copy 2 Outlines.Group 1.Stroke 1": foregroundColor, + "Artboard Copy 2 Outlines.Group 4.Stroke 1": foregroundColor, + "Artboard Copy Outlines.Group 1.Stroke 1": foregroundColor, + ], size: CGSize(width: 30.0, height: 30.0) )), environment: {}, @@ -141,11 +142,11 @@ public final class AudioTranscriptionButtonComponent: Component { component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: "voicets_progress", - colors: [ - "Rectangle 60.Rectangle 60.Stroke 1": foregroundColor - ], mode: .animating(loop: true) ), + colors: [ + "Rectangle 60.Rectangle 60.Stroke 1": foregroundColor + ], size: progressFrame.size )), environment: {}, diff --git a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift index ff7e3521df..e45f38fbbb 100644 --- a/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift +++ b/submodules/TelegramUI/Components/AudioTranscriptionPendingIndicatorComponent/Sources/AudioTranscriptionPendingIndicatorComponent.swift @@ -142,13 +142,13 @@ public final class AudioTranscriptionPendingLottieIndicatorComponent: Component component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: "animated_text_dots", - colors: [ - "Comp 1.Point 3.Group 1.Fill 1": component.color, - "Comp 1.Point 2.Group 1.Fill 1": component.color, - "Comp 1.Point 1.Group 1.Fill 1": component.color - ], mode: .animating(loop: true) ), + colors: [ + "Comp 1.Point 3.Group 1.Fill 1": component.color, + "Comp 1.Point 2.Group 1.Fill 1": component.color, + "Comp 1.Point 1.Group 1.Fill 1": component.color + ], size: animationSize )), environment: {}, diff --git a/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD new file mode 100644 index 0000000000..3ae830cb24 --- /dev/null +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD @@ -0,0 +1,21 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ChatInputPanelContainer", + module_name = "ChatInputPanelContainer", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + "//submodules/Display:Display", + "//submodules/Components/PagerComponent:PagerComponent", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift new file mode 100644 index 0000000000..a333939a18 --- /dev/null +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift @@ -0,0 +1,311 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import PagerComponent + +private func traceScrollView(view: UIView, point: CGPoint) -> (UIScrollView?, Bool) { + for subview in view.subviews.reversed() { + let subviewPoint = view.convert(point, to: subview) + if subview.frame.contains(point) || subview is PagerExternalTopPanelContainer { + let (result, shouldContinue) = traceScrollView(view: subview, point: subviewPoint) + if let result = result { + return (result, false) + } else if subview.backgroundColor != nil { + return (nil, false) + } else if !shouldContinue { + return (nil, false) + } + } + } + if let scrollView = view as? UIScrollView { + return (scrollView, false) + } + return (nil, true) +} + +private func traceScrollViewUp(view: UIView) -> UIScrollView? { + if let scrollView = view as? UIScrollView { + return scrollView + } else if let superview = view.superview { + return traceScrollViewUp(view: superview) + } else { + return nil + } +} + +private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecognizerDelegate { + enum LockDirection { + case up + case down + case any + } + + var requiredLockDirection: LockDirection = .up + + private var beginPosition = CGPoint() + private var currentTranslation = CGPoint() + + override public init(target: Any?, action: Selector?) { + super.init(target: target, action: action) + + self.delegate = self + } + + override public func reset() { + super.reset() + + self.state = .possible + self.currentTranslation = CGPoint() + } + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + if let _ = otherGestureRecognizer.view as? PagerExpandableScrollView { + return true + } + + if let _ = gestureRecognizer as? PagerPanGestureRecognizer { + return true + } + + return true + } + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { + if let _ = otherGestureRecognizer.view as? PagerExpandableScrollView { + return true + } + if otherGestureRecognizer is UIPanGestureRecognizer { + return true + } + return false + } + + override public func touchesBegan(_ touches: Set, with event: UIEvent) { + super.touchesBegan(touches, with: event) + + guard let touch = touches.first, let view = self.view else { + self.state = .failed + return + } + + var found = false + let point = touch.location(in: self.view) + + let hitView = view.hitTest(point, with: event) + + if let _ = hitView as? UIButton { + } else if let hitView = hitView, hitView.asyncdisplaykit_node is ASButtonNode { + } else { + if let scrollView = traceScrollView(view: view, point: point).0 ?? hitView.flatMap(traceScrollViewUp) { + if scrollView is ListViewScroller || scrollView is GridNodeScrollerView || scrollView.asyncdisplaykit_node is ASScrollNode { + found = false + } else { + found = true + } + } else { + found = true + } + } + + if found { + self.beginPosition = point + } else { + self.state = .failed + } + } + + override public func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) + + guard let touch = touches.first, let view = self.view else { + self.state = .failed + return + } + + let point = touch.location(in: self.view) + + let translation = CGPoint(x: point.x - self.beginPosition.x, y: point.y - self.beginPosition.y) + self.currentTranslation = translation + + if self.state == .possible { + if abs(translation.x) > 8.0 { + self.state = .failed + return + } + var lockDirection: LockDirection? + let point = touch.location(in: self.view) + let tracedView = view.hitTest(point, with: event) + if let scrollView = traceScrollView(view: view, point: point).0 { + if !(scrollView is PagerExpandableScrollView) { + lockDirection = .any + } else { + let contentOffset = scrollView.contentOffset + let contentInset = scrollView.contentInset + if contentOffset.y <= contentInset.top { + lockDirection = .down + } + } + } else { + lockDirection = .any + } + if let lockDirection = lockDirection { + if abs(translation.y) > 2.0 { + switch lockDirection { + case .up: + if translation.y < 0.0 { + if let tracedView = tracedView { + cancelParentGestures(view: tracedView, ignore: [self]) + } + self.state = .began + } else { + self.state = .failed + } + case .down: + if translation.y > 0.0 { + if let tracedView = tracedView { + cancelParentGestures(view: tracedView, ignore: [self]) + } + self.state = .began + } else { + self.state = .failed + } + case .any: + if let tracedView = tracedView { + cancelParentGestures(view: tracedView, ignore: [self]) + } + self.state = .began + } + } + } else { + self.state = .failed + } + } else { + self.state = .changed + } + } + + override public func touchesEnded(_ touches: Set, with event: UIEvent) { + super.touchesEnded(touches, with: event) + + self.state = .ended + } + + override public func touchesCancelled(_ touches: Set, with event: UIEvent) { + super.touchesCancelled(touches, with: event) + + self.state = .cancelled + } + + func translation() -> CGPoint { + return self.currentTranslation + } + + func velocity() -> CGPoint { + return CGPoint() + } +} + +public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { + public var expansionUpdated: ((ContainedViewLayoutTransition) -> Void)? + + private var expansionRecognizer: ExpansionPanRecognizer? + + private var scrollableDistance: CGFloat? + public private(set) var initialExpansionFraction: CGFloat = 0.0 + public private(set) var expansionFraction: CGFloat = 0.0 + public private(set) var stableIsExpanded: Bool = false + + override public init() { + super.init() + + let expansionRecognizer = ExpansionPanRecognizer(target: self, action: #selector(self.panGesture(_:))) + self.expansionRecognizer = expansionRecognizer + self.view.addGestureRecognizer(expansionRecognizer) + expansionRecognizer.isEnabled = false + } + + @objc private func panGesture(_ recognizer: ExpansionPanRecognizer) { + switch recognizer.state { + case .began: + guard let _ = self.scrollableDistance else { + return + } + self.initialExpansionFraction = self.expansionFraction + case .changed: + guard let scrollableDistance = self.scrollableDistance else { + return + } + + let delta = -recognizer.translation().y / scrollableDistance + + self.expansionFraction = max(0.0, min(1.0, self.initialExpansionFraction + delta)) + self.expansionUpdated?(.immediate) + case .ended, .cancelled: + guard let _ = self.scrollableDistance else { + return + } + + let velocity = recognizer.velocity() + if abs(self.initialExpansionFraction - self.expansionFraction) > 0.25 { + if self.initialExpansionFraction < 0.5 { + self.expansionFraction = 1.0 + } else { + self.expansionFraction = 0.0 + } + } else if abs(velocity.y) > 100.0 { + if velocity.y < 0.0 { + self.expansionFraction = 1.0 + } else { + self.expansionFraction = 0.0 + } + } else { + if self.initialExpansionFraction < 0.5 { + self.expansionFraction = 0.0 + } else { + self.expansionFraction = 1.0 + } + } + + self.stableIsExpanded = self.expansionFraction == 1.0 + + if let expansionRecognizer = self.expansionRecognizer { + expansionRecognizer.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down + } + + self.expansionUpdated?(.animated(duration: 0.4, curve: .spring)) + default: + break + } + } + + public func update(size: CGSize, scrollableDistance: CGFloat, isExpansionEnabled: Bool, transition: ContainedViewLayoutTransition) { + self.expansionRecognizer?.isEnabled = isExpansionEnabled + + self.scrollableDistance = scrollableDistance + } + + public func expand() { + self.expansionFraction = 1.0 + self.expansionRecognizer?.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down + self.stableIsExpanded = self.expansionFraction == 1.0 + } + + public func collapse() { + self.expansionFraction = 0.0 + self.expansionRecognizer?.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down + self.stableIsExpanded = self.expansionFraction == 1.0 + } + + public func toggleIfEnabled() { + if let expansionRecognizer = self.expansionRecognizer, expansionRecognizer.isEnabled { + if self.expansionFraction == 0.0 { + self.expansionFraction = 1.0 + } else { + self.expansionFraction = 0.0 + } + self.stableIsExpanded = self.expansionFraction == 1.0 + self.expansionUpdated?(.animated(duration: 0.4, curve: .spring)) + } + } +} diff --git a/submodules/TelegramUI/Components/EmojiKeyboard/Sources/EmojiKeyboard.swift b/submodules/TelegramUI/Components/EmojiKeyboard/Sources/EmojiKeyboard.swift deleted file mode 100644 index 2cc37ab552..0000000000 --- a/submodules/TelegramUI/Components/EmojiKeyboard/Sources/EmojiKeyboard.swift +++ /dev/null @@ -1,4 +0,0 @@ -import Foundation -import UIKit -import Display - diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/BUILD b/submodules/TelegramUI/Components/EmojiTextAttachmentView/BUILD index ff1faa52e0..37de259bd2 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/BUILD +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/BUILD @@ -21,6 +21,7 @@ swift_library( "//submodules/AccountContext:AccountContext", "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", "//submodules/TelegramUI/Components/LottieAnimationCache:LottieAnimationCache", + "//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", "//submodules/ShimmerEffect:ShimmerEffect", ], diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 700adef954..b1ec5fa256 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -11,25 +11,40 @@ import TelegramCore import Postbox import AnimationCache import LottieAnimationCache +import VideoAnimationCache import MultiAnimationRenderer import ShimmerEffect +import TextFormat public final class InlineStickerItemLayer: MultiAnimationRenderTarget { public static let queue = Queue() public struct Key: Hashable { - public var id: MediaId + public var id: Int64 public var index: Int - public init(id: MediaId, index: Int) { + public init(id: Int64, index: Int) { self.id = id self.index = index } } - private let file: TelegramMediaFile + private let context: AccountContext + private let emoji: ChatTextInputTextCustomEmojiAttribute + private let cache: AnimationCache + private let renderer: MultiAnimationRenderer + private let placeholderColor: UIColor + + private let pointSize: CGSize + private let pixelSize: CGSize + + private var isDisplayingPlaceholder: Bool = false + + private var file: TelegramMediaFile? + private var infoDisposable: Disposable? private var disposable: Disposable? private var fetchDisposable: Disposable? + private var loadDisposable: Disposable? private var isInHierarchyValue: Bool = false public var isVisibleForAnimations: Bool = false { @@ -39,45 +54,33 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } } } - private var displayLink: ConstantDisplayLinkAnimator? - public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, file: TelegramMediaFile, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.file = file + public init(context: AccountContext, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { + self.context = context + self.emoji = emoji + self.cache = cache + self.renderer = renderer + self.placeholderColor = placeholderColor + + let scale = min(2.0, UIScreenScale) + self.pointSize = pointSize + self.pixelSize = CGSize(width: self.pointSize.width * scale, height: self.pointSize.height * scale) super.init() - if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation) { - let size = CGSize(width: 24.0, height: 24.0) - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) { - self.contents = image.cgImage - } - } - } - - self.disposable = renderer.add(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, fetch: { writer in - let source = AnimatedStickerResourceSource(account: context.account, resource: file.resource, fitzModifier: nil, isVideo: false) - - let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in - guard let result = result else { + if let file = file { + self.updateFile(file: file, attemptSynchronousLoad: attemptSynchronousLoad) + } else { + self.infoDisposable = (context.engine.stickers.resolveInlineStickers(fileIds: [emoji.fileId]) + |> deliverOnMainQueue).start(next: { [weak self] files in + guard let strongSelf = self else { return } - - guard let data = try? Data(contentsOf: URL(fileURLWithPath: result)) else { - writer.finish() - return + if let file = files[emoji.fileId] { + strongSelf.updateFile(file: file, attemptSynchronousLoad: false) } - let scale = min(2.0, UIScreenScale) - cacheLottieAnimation(data: data, width: Int(24 * scale), height: Int(24 * scale), writer: writer) }) - - let fetchDisposable = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() - } - }) + } } override public init(layer: Any) { @@ -89,6 +92,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } deinit { + self.loadDisposable?.dispose() + self.infoDisposable?.dispose() self.disposable?.dispose() self.fetchDisposable?.dispose() } @@ -96,10 +101,11 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { override public func action(forKey event: String) -> CAAction? { if event == kCAOnOrderIn { self.isInHierarchyValue = true + self.updatePlayback() } else if event == kCAOnOrderOut { self.isInHierarchyValue = false + self.updatePlayback() } - self.updatePlayback() return nullAction } @@ -108,13 +114,143 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { self.shouldBeAnimating = shouldBePlaying } + + private func updateFile(file: TelegramMediaFile, attemptSynchronousLoad: Bool) { + if self.file?.fileId == file.fileId { + return + } + + self.file = file + + if attemptSynchronousLoad { + if !self.renderer.loadFirstFrameSynchronously(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize) { + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.pointSize, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: self.placeholderColor) { + self.contents = image.cgImage + self.isDisplayingPlaceholder = true + } + } + + self.loadAnimation() + } else { + let pointSize = self.pointSize + let placeholderColor = self.placeholderColor + self.loadDisposable = self.renderer.loadFirstFrame(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, completion: { [weak self] result in + if !result { + MultiAnimationRendererImpl.firstFrameQueue.async { + let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: pointSize, scale: min(2.0, UIScreenScale), imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) + + DispatchQueue.main.async { + guard let strongSelf = self else { + return + } + if let image = image { + strongSelf.contents = image.cgImage + strongSelf.isDisplayingPlaceholder = true + } + strongSelf.loadAnimation() + } + } + } else { + guard let strongSelf = self else { + return + } + strongSelf.loadAnimation() + } + }) + } + } + + private func loadAnimation() { + guard let file = self.file else { + return + } + + let context = self.context + if file.isAnimatedSticker || file.isVideoEmoji { + self.disposable = renderer.add(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: { size, writer in + let source = AnimatedStickerResourceSource(account: context.account, resource: file.resource, fitzModifier: nil, isVideo: false) + + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { + return + } + + if file.isVideoEmoji { + cacheVideoAnimation(path: result, width: Int(size.width), height: Int(size.height), writer: writer) + } else { + guard let data = try? Data(contentsOf: URL(fileURLWithPath: result)) else { + writer.finish() + return + } + cacheLottieAnimation(data: data, width: Int(size.width), height: Int(size.height), writer: writer) + } + }) + + let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: .customEmoji(media: file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } else { + self.disposable = renderer.add(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: { size, writer in + let dataDisposable = context.account.postbox.mediaBox.resourceData(file.resource).start(next: { result in + guard result.complete else { + return + } + + cacheStillSticker(path: result.path, width: Int(size.width), height: Int(size.height), writer: writer) + }) + + let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: .customEmoji(media: file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } + } + + override public func updateDisplayPlaceholder(displayPlaceholder: Bool) { + if self.isDisplayingPlaceholder == displayPlaceholder { + return + } + self.isDisplayingPlaceholder = displayPlaceholder + } + + override public func transitionToContents(_ contents: AnyObject) { + if self.isDisplayingPlaceholder { + self.isDisplayingPlaceholder = false + + if let current = self.contents { + let previousLayer = SimpleLayer() + previousLayer.contents = current + previousLayer.frame = self.frame + self.superlayer?.insertSublayer(previousLayer, below: self) + previousLayer.opacity = 0.0 + previousLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak previousLayer] _ in + previousLayer?.removeFromSuperlayer() + }) + + self.contents = contents + self.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) + } else { + self.contents = contents + self.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } else { + self.contents = contents + } + } } public final class EmojiTextAttachmentView: UIView { private let contentLayer: InlineStickerItemLayer - public init(context: AccountContext, file: TelegramMediaFile, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor) + public init(context: AccountContext, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { + self.contentLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: pointSize) super.init(frame: CGRect()) @@ -129,6 +265,6 @@ public final class EmojiTextAttachmentView: UIView { override public func layoutSubviews() { super.layoutSubviews() - self.contentLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: -2.0), size: CGSize(width: self.bounds.width - 0.0, height: self.bounds.height + 9.0)) + self.contentLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: self.bounds.width, height: self.bounds.height)) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD new file mode 100644 index 0000000000..038729a74d --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -0,0 +1,48 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "EntityKeyboard", + module_name = "EntityKeyboard", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/Display:Display", + "//submodules/ComponentFlow:ComponentFlow", + "//submodules/Components/PagerComponent:PagerComponent", + "//submodules/Components/BlurredBackgroundComponent:BlurredBackgroundComponent", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", + "//submodules/Components/BundleIconComponent:BundleIconComponent", + "//submodules/TelegramPresentationData:TelegramPresentationData", + "//submodules/TelegramCore:TelegramCore", + "//submodules/Postbox:Postbox", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", + "//submodules/YuvConversion:YuvConversion", + "//submodules/AccountContext:AccountContext", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/LottieAnimationCache:LottieAnimationCache", + "//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/TelegramUI/Components/MultiVideoRenderer:MultiVideoRenderer", + "//submodules/SoftwareVideo:SoftwareVideo", + "//submodules/ShimmerEffect:ShimmerEffect", + "//submodules/PhotoResources:PhotoResources", + "//submodules/StickerResources:StickerResources", + "//submodules/AppBundle:AppBundle", + "//submodules/ContextUI:ContextUI", + "//submodules/PremiumUI:PremiumUI", + "//submodules/StickerPeekUI:StickerPeekUI", + "//submodules/UndoUI:UndoUI", + "//submodules/Components/MultilineTextComponent:MultilineTextComponent", + "//submodules/Components/SolidRoundedButtonComponent:SolidRoundedButtonComponent", + "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift new file mode 100644 index 0000000000..4cc3c0d4fa --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -0,0 +1,3817 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import MultiAnimationRenderer +import AnimationCache +import AccountContext +import LottieAnimationCache +import VideoAnimationCache +import AnimatedStickerNode +import TelegramAnimatedStickerNode +import SwiftSignalKit +import ShimmerEffect +import PagerComponent +import StickerResources +import AppBundle +import ContextUI +import PremiumUI +import StickerPeekUI +import UndoUI +import AudioToolbox +import SolidRoundedButtonComponent + +private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) +private let featuredBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelBadgeAdd"), color: .white) +private let lockedBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelBadgeLock"), color: .white) + +private final class PassthroughLayer: CALayer { + var mirrorLayer: CALayer? + + override init() { + super.init() + } + + override init(layer: Any) { + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var position: CGPoint { + get { + return super.position + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.position = value + } + super.position = value + } + } + + override var bounds: CGRect { + get { + return super.bounds + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.bounds = value + } + super.bounds = value + } + } + + override var opacity: Float { + get { + return super.opacity + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.opacity = value + } + super.opacity = value + } + } + + override var sublayerTransform: CATransform3D { + get { + return super.sublayerTransform + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.sublayerTransform = value + } + super.sublayerTransform = value + } + } + + override var transform: CATransform3D { + get { + return super.transform + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.transform = value + } + super.transform = value + } + } + + override func add(_ animation: CAAnimation, forKey key: String?) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.add(animation, forKey: key) + } + + super.add(animation, forKey: key) + } + + override func removeAllAnimations() { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAllAnimations() + } + + super.removeAllAnimations() + } + + override func removeAnimation(forKey: String) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAnimation(forKey: forKey) + } + + super.removeAnimation(forKey: forKey) + } +} + +private class PassthroughShapeLayer: CAShapeLayer { + var mirrorLayer: CAShapeLayer? + + override init() { + super.init() + } + + override init(layer: Any) { + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var position: CGPoint { + get { + return super.position + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.position = value + } + super.position = value + } + } + + override var bounds: CGRect { + get { + return super.bounds + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.bounds = value + } + super.bounds = value + } + } + + override var opacity: Float { + get { + return super.opacity + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.opacity = value + } + super.opacity = value + } + } + + override var sublayerTransform: CATransform3D { + get { + return super.sublayerTransform + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.sublayerTransform = value + } + super.sublayerTransform = value + } + } + + override var transform: CATransform3D { + get { + return super.transform + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.transform = value + } + super.transform = value + } + } + + override var path: CGPath? { + get { + return super.path + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.path = value + } + super.path = value + } + } + + override var fillColor: CGColor? { + get { + return super.fillColor + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.fillColor = value + } + super.fillColor = value + } + } + + override var fillRule: CAShapeLayerFillRule { + get { + return super.fillRule + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.fillRule = value + } + super.fillRule = value + } + } + + override var strokeColor: CGColor? { + get { + return super.strokeColor + } set(value) { + /*if let mirrorLayer = self.mirrorLayer { + mirrorLayer.strokeColor = value + }*/ + super.strokeColor = value + } + } + + override var strokeStart: CGFloat { + get { + return super.strokeStart + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.strokeStart = value + } + super.strokeStart = value + } + } + + override var strokeEnd: CGFloat { + get { + return super.strokeEnd + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.strokeEnd = value + } + super.strokeEnd = value + } + } + + override var lineWidth: CGFloat { + get { + return super.lineWidth + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.lineWidth = value + } + super.lineWidth = value + } + } + + override var miterLimit: CGFloat { + get { + return super.miterLimit + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.miterLimit = value + } + super.miterLimit = value + } + } + + override var lineCap: CAShapeLayerLineCap { + get { + return super.lineCap + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.lineCap = value + } + super.lineCap = value + } + } + + override var lineJoin: CAShapeLayerLineJoin { + get { + return super.lineJoin + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.lineJoin = value + } + super.lineJoin = value + } + } + + override var lineDashPhase: CGFloat { + get { + return super.lineDashPhase + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.lineDashPhase = value + } + super.lineDashPhase = value + } + } + + override var lineDashPattern: [NSNumber]? { + get { + return super.lineDashPattern + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.lineDashPattern = value + } + super.lineDashPattern = value + } + } + + override func add(_ animation: CAAnimation, forKey key: String?) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.add(animation, forKey: key) + } + + super.add(animation, forKey: key) + } + + override func removeAllAnimations() { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAllAnimations() + } + + super.removeAllAnimations() + } + + override func removeAnimation(forKey: String) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAnimation(forKey: forKey) + } + + super.removeAnimation(forKey: forKey) + } +} + +private final class PremiumBadgeView: UIView { + private var badge: EmojiPagerContentComponent.View.ItemLayer.Badge? + + let contentLayer: SimpleLayer + private let overlayColorLayer: SimpleLayer + private let iconLayer: SimpleLayer + + init() { + self.contentLayer = SimpleLayer() + self.contentLayer.contentsGravity = .resize + self.contentLayer.masksToBounds = true + + self.overlayColorLayer = SimpleLayer() + self.overlayColorLayer.masksToBounds = true + + self.iconLayer = SimpleLayer() + + super.init(frame: CGRect()) + + self.layer.addSublayer(self.contentLayer) + self.layer.addSublayer(self.overlayColorLayer) + self.layer.addSublayer(self.iconLayer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(transition: Transition, badge: EmojiPagerContentComponent.View.ItemLayer.Badge, backgroundColor: UIColor, size: CGSize) { + if self.badge != badge { + self.badge = badge + + switch badge { + case .premium: + self.iconLayer.contents = premiumBadgeIcon?.cgImage + case .featured: + self.iconLayer.contents = featuredBadgeIcon?.cgImage + case .locked: + self.iconLayer.contents = lockedBadgeIcon?.cgImage + } + } + + let iconInset: CGFloat + switch badge { + case .premium: + iconInset = 2.0 + case .featured: + iconInset = 0.0 + case .locked: + iconInset = 0.0 + } + + self.overlayColorLayer.backgroundColor = backgroundColor.cgColor + + transition.setFrame(layer: self.contentLayer, frame: CGRect(origin: CGPoint(), size: size)) + transition.setCornerRadius(layer: self.contentLayer, cornerRadius: min(size.width / 2.0, size.height / 2.0)) + + transition.setFrame(layer: self.overlayColorLayer, frame: CGRect(origin: CGPoint(), size: size)) + transition.setCornerRadius(layer: self.overlayColorLayer, cornerRadius: min(size.width / 2.0, size.height / 2.0)) + + transition.setFrame(layer: self.iconLayer, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: iconInset, dy: iconInset)) + } +} + +private final class GroupHeaderActionButton: UIButton { + private var currentTextLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? + private let backgroundLayer: SimpleLayer + private let textLayer: SimpleLayer + private let pressed: () -> Void + + init(pressed: @escaping () -> Void) { + self.pressed = pressed + + self.backgroundLayer = SimpleLayer() + self.backgroundLayer.masksToBounds = true + + self.textLayer = SimpleLayer() + + super.init(frame: CGRect()) + + self.layer.addSublayer(self.backgroundLayer) + self.layer.addSublayer(self.textLayer) + + self.addTarget(self, action: #selector(self.onPressed), for: .touchUpInside) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + @objc private func onPressed() { + self.pressed() + } + + override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { + self.alpha = 0.6 + + return super.beginTracking(touch, with: event) + } + + override func endTracking(_ touch: UITouch?, with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.endTracking(touch, with: event) + } + + override func cancelTracking(with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.cancelTracking(with: event) + } + + override func touchesCancelled(_ touches: Set, with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.touchesCancelled(touches, with: event) + } + + func update(theme: PresentationTheme, title: String) -> CGSize { + let textConstrainedWidth: CGFloat = 100.0 + let color = theme.list.itemCheckColors.foregroundColor + + self.backgroundLayer.backgroundColor = theme.list.itemCheckColors.fillColor.cgColor + + let textSize: CGSize + if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == textConstrainedWidth { + textSize = currentTextLayout.size + } else { + let font: UIFont = Font.semibold(15.0) + let string = NSAttributedString(string: title.uppercased(), font: font, textColor: color) + let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + textSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) + self.textLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + string.draw(in: stringBounds) + + UIGraphicsPopContext() + })?.cgImage + self.currentTextLayout = (title, color, textConstrainedWidth, textSize) + } + + let size = CGSize(width: textSize.width + 16.0 * 2.0, height: 28.0) + + let textFrame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((size.height - textSize.height) / 2.0)), size: textSize) + self.textLayer.frame = textFrame + + self.backgroundLayer.frame = CGRect(origin: CGPoint(), size: size) + self.backgroundLayer.cornerRadius = min(size.width, size.height) / 2.0 + + return size + } +} + +private final class GroupHeaderLayer: UIView { + override static var layerClass: AnyClass { + return PassthroughLayer.self + } + + private let actionPressed: () -> Void + private let performItemAction: (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void + + private let textLayer: SimpleLayer + private let tintTextLayer: SimpleLayer + + private var subtitleLayer: SimpleLayer? + private var tintSubtitleLayer: SimpleLayer? + private var lockIconLayer: SimpleLayer? + private var tintLockIconLayer: SimpleLayer? + private(set) var clearIconLayer: SimpleLayer? + private var tintClearIconLayer: SimpleLayer? + private var separatorLayer: SimpleLayer? + private var tintSeparatorLayer: SimpleLayer? + private var actionButton: GroupHeaderActionButton? + + private var groupEmbeddedView: GroupEmbeddedView? + + private var theme: PresentationTheme? + + private var currentTextLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? + private var currentSubtitleLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? + + let tintContentLayer: SimpleLayer + + init(actionPressed: @escaping () -> Void, performItemAction: @escaping (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void) { + self.actionPressed = actionPressed + self.performItemAction = performItemAction + + self.textLayer = SimpleLayer() + self.tintTextLayer = SimpleLayer() + + self.tintContentLayer = SimpleLayer() + + super.init(frame: CGRect()) + + self.layer.addSublayer(self.textLayer) + self.tintContentLayer.addSublayer(self.tintTextLayer) + + (self.layer as? PassthroughLayer)?.mirrorLayer = self.tintContentLayer + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update( + context: AccountContext, + theme: PresentationTheme, + layoutType: EmojiPagerContentComponent.ItemLayoutType, + hasTopSeparator: Bool, + actionButtonTitle: String?, + title: String, + subtitle: String?, + isPremiumLocked: Bool, + hasClear: Bool, + embeddedItems: [EmojiPagerContentComponent.Item]?, + constrainedSize: CGSize, + insets: UIEdgeInsets, + cache: AnimationCache, + renderer: MultiAnimationRenderer, + attemptSynchronousLoad: Bool + ) -> (size: CGSize, centralContentWidth: CGFloat) { + var themeUpdated = false + if self.theme !== theme { + self.theme = theme + themeUpdated = true + } + + let textOffsetY: CGFloat + if hasTopSeparator { + textOffsetY = 9.0 + } else { + textOffsetY = 0.0 + } + + let color: UIColor + let needsTintText: Bool + if subtitle != nil { + color = theme.chat.inputPanel.primaryTextColor + needsTintText = false + } else { + color = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor + needsTintText = true + } + let subtitleColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor + + let titleHorizontalOffset: CGFloat + if isPremiumLocked { + titleHorizontalOffset = 10.0 + 2.0 + } else { + titleHorizontalOffset = 0.0 + } + + var actionButtonSize: CGSize? + if let actionButtonTitle = actionButtonTitle { + let actionButton: GroupHeaderActionButton + if let current = self.actionButton { + actionButton = current + } else { + actionButton = GroupHeaderActionButton(pressed: self.actionPressed) + self.actionButton = actionButton + self.addSubview(actionButton) + } + + actionButtonSize = actionButton.update(theme: theme, title: actionButtonTitle) + } else { + if let actionButton = self.actionButton { + self.actionButton = nil + actionButton.removeFromSuperview() + } + } + + var textConstrainedWidth = constrainedSize.width - titleHorizontalOffset - 10.0 + if let actionButtonSize = actionButtonSize { + textConstrainedWidth -= actionButtonSize.width - 8.0 + } + + let textSize: CGSize + if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == textConstrainedWidth { + textSize = currentTextLayout.size + } else { + let font: UIFont + let stringValue: String + if subtitle == nil { + font = Font.medium(13.0) + stringValue = title.uppercased() + } else { + font = Font.semibold(16.0) + stringValue = title + } + let string = NSAttributedString(string: stringValue, font: font, textColor: color) + let whiteString = NSAttributedString(string: stringValue, font: font, textColor: .white) + let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + textSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) + self.textLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + string.draw(in: stringBounds) + + UIGraphicsPopContext() + })?.cgImage + self.tintTextLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + whiteString.draw(in: stringBounds) + + UIGraphicsPopContext() + })?.cgImage + self.currentTextLayout = (title, color, textConstrainedWidth, textSize) + } + + let textFrame: CGRect + if subtitle == nil { + textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), y: textOffsetY), size: textSize) + } else { + textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) + } + self.textLayer.frame = textFrame + self.tintTextLayer.frame = textFrame + self.tintTextLayer.isHidden = !needsTintText + + if isPremiumLocked { + let lockIconLayer: SimpleLayer + if let current = self.lockIconLayer { + lockIconLayer = current + } else { + lockIconLayer = SimpleLayer() + self.lockIconLayer = lockIconLayer + self.layer.addSublayer(lockIconLayer) + } + if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: color) { + let imageSize = image.size + lockIconLayer.contents = image.cgImage + lockIconLayer.frame = CGRect(origin: CGPoint(x: textFrame.minX - imageSize.width - 3.0, y: 2.0 + UIScreenPixel), size: imageSize) + } else { + lockIconLayer.contents = nil + } + + let tintLockIconLayer: SimpleLayer + if let current = self.tintLockIconLayer { + tintLockIconLayer = current + } else { + tintLockIconLayer = SimpleLayer() + self.tintLockIconLayer = tintLockIconLayer + self.tintContentLayer.addSublayer(tintLockIconLayer) + } + if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: .white) { + tintLockIconLayer.contents = image.cgImage + tintLockIconLayer.frame = lockIconLayer.frame + } else { + tintLockIconLayer.contents = nil + } + } else { + if let lockIconLayer = self.lockIconLayer { + self.lockIconLayer = nil + lockIconLayer.removeFromSuperlayer() + } + if let tintLockIconLayer = self.tintLockIconLayer { + self.tintLockIconLayer = nil + tintLockIconLayer.removeFromSuperlayer() + } + } + + let subtitleSize: CGSize + if let subtitle = subtitle { + var updateSubtitleContents: UIImage? + var updateTintSubtitleContents: UIImage? + if let currentSubtitleLayout = self.currentSubtitleLayout, currentSubtitleLayout.string == subtitle, currentSubtitleLayout.color == subtitleColor, currentSubtitleLayout.constrainedWidth == textConstrainedWidth { + subtitleSize = currentSubtitleLayout.size + } else { + let string = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: subtitleColor) + let whiteString = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: .white) + let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + subtitleSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) + updateSubtitleContents = generateImage(subtitleSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + string.draw(in: stringBounds) + + UIGraphicsPopContext() + }) + updateTintSubtitleContents = generateImage(subtitleSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + whiteString.draw(in: stringBounds) + + UIGraphicsPopContext() + }) + self.currentSubtitleLayout = (subtitle, subtitleColor, textConstrainedWidth, subtitleSize) + } + + let subtitleLayer: SimpleLayer + if let current = self.subtitleLayer { + subtitleLayer = current + } else { + subtitleLayer = SimpleLayer() + self.subtitleLayer = subtitleLayer + self.layer.addSublayer(subtitleLayer) + } + + if let updateSubtitleContents = updateSubtitleContents { + subtitleLayer.contents = updateSubtitleContents.cgImage + } + + let tintSubtitleLayer: SimpleLayer + if let current = self.tintSubtitleLayer { + tintSubtitleLayer = current + } else { + tintSubtitleLayer = SimpleLayer() + self.tintSubtitleLayer = tintSubtitleLayer + self.tintContentLayer.addSublayer(tintSubtitleLayer) + } + + if let updateTintSubtitleContents = updateTintSubtitleContents { + tintSubtitleLayer.contents = updateTintSubtitleContents.cgImage + } + + let subtitleFrame = CGRect(origin: CGPoint(x: 0.0, y: textFrame.maxY + 1.0), size: subtitleSize) + subtitleLayer.frame = subtitleFrame + tintSubtitleLayer.frame = subtitleFrame + } else { + subtitleSize = CGSize() + if let subtitleLayer = self.subtitleLayer { + self.subtitleLayer = nil + subtitleLayer.removeFromSuperlayer() + } + } + + var clearWidth: CGFloat = 0.0 + if hasClear { + var updateImage = themeUpdated + + let clearIconLayer: SimpleLayer + if let current = self.clearIconLayer { + clearIconLayer = current + } else { + updateImage = true + clearIconLayer = SimpleLayer() + self.clearIconLayer = clearIconLayer + self.layer.addSublayer(clearIconLayer) + } + let tintClearIconLayer: SimpleLayer + if let current = self.tintClearIconLayer { + tintClearIconLayer = current + } else { + updateImage = true + tintClearIconLayer = SimpleLayer() + self.tintClearIconLayer = tintClearIconLayer + self.tintContentLayer.addSublayer(tintClearIconLayer) + } + + var clearSize = clearIconLayer.bounds.size + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) { + clearSize = image.size + clearIconLayer.contents = image.cgImage + } + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: .white) { + tintClearIconLayer.contents = image.cgImage + } + + clearIconLayer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - clearSize.width, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) + + tintClearIconLayer.frame = clearIconLayer.frame + clearWidth = 4.0 + clearSize.width + } else { + if let clearIconLayer = self.clearIconLayer { + self.clearIconLayer = nil + clearIconLayer.removeFromSuperlayer() + } + if let tintClearIconLayer = self.tintClearIconLayer { + self.tintClearIconLayer = nil + tintClearIconLayer.removeFromSuperlayer() + } + } + + var size: CGSize + size = CGSize(width: constrainedSize.width, height: constrainedSize.height) + + if let embeddedItems = embeddedItems { + let groupEmbeddedView: GroupEmbeddedView + if let current = self.groupEmbeddedView { + groupEmbeddedView = current + } else { + groupEmbeddedView = GroupEmbeddedView(performItemAction: self.performItemAction) + self.groupEmbeddedView = groupEmbeddedView + self.addSubview(groupEmbeddedView) + } + + let groupEmbeddedViewSize = CGSize(width: constrainedSize.width + insets.left + insets.right, height: 36.0) + groupEmbeddedView.frame = CGRect(origin: CGPoint(x: -insets.left, y: size.height - groupEmbeddedViewSize.height), size: groupEmbeddedViewSize) + groupEmbeddedView.update( + context: context, + theme: theme, + insets: insets, + size: groupEmbeddedViewSize, + items: embeddedItems, + cache: cache, + renderer: renderer, + attemptSynchronousLoad: attemptSynchronousLoad + ) + } else { + if let groupEmbeddedView = self.groupEmbeddedView { + self.groupEmbeddedView = nil + groupEmbeddedView.removeFromSuperview() + } + } + + if let actionButtonSize = actionButtonSize, let actionButton = self.actionButton { + actionButton.frame = CGRect(origin: CGPoint(x: size.width - actionButtonSize.width, y: textFrame.minY + 3.0), size: actionButtonSize) + } + + if hasTopSeparator { + let separatorLayer: SimpleLayer + if let current = self.separatorLayer { + separatorLayer = current + } else { + separatorLayer = SimpleLayer() + self.separatorLayer = separatorLayer + self.layer.addSublayer(separatorLayer) + } + separatorLayer.backgroundColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor + separatorLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: UIScreenPixel)) + + let tintSeparatorLayer: SimpleLayer + if let current = self.tintSeparatorLayer { + tintSeparatorLayer = current + } else { + tintSeparatorLayer = SimpleLayer() + self.tintSeparatorLayer = tintSeparatorLayer + self.tintContentLayer.addSublayer(tintSeparatorLayer) + } + tintSeparatorLayer.backgroundColor = UIColor.white.cgColor + tintSeparatorLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: UIScreenPixel)) + } else { + if let separatorLayer = self.separatorLayer { + self.separatorLayer = separatorLayer + separatorLayer.removeFromSuperlayer() + } + if let tintSeparatorLayer = self.tintSeparatorLayer { + self.tintSeparatorLayer = tintSeparatorLayer + tintSeparatorLayer.removeFromSuperlayer() + } + } + + return (size, titleHorizontalOffset + textSize.width + clearWidth) + } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + return super.hitTest(point, with: event) + } + + func tapGesture(_ recognizer: UITapGestureRecognizer) -> Bool { + if let groupEmbeddedView = self.groupEmbeddedView { + return groupEmbeddedView.tapGesture(recognizer) + } else { + return false + } + } +} + +private final class GroupEmbeddedView: UIScrollView, UIScrollViewDelegate, PagerExpandableScrollView { + private struct ItemLayout { + var itemSize: CGFloat + var itemSpacing: CGFloat + var sideInset: CGFloat + var itemCount: Int + var contentSize: CGSize + + init(height: CGFloat, sideInset: CGFloat, itemCount: Int) { + self.itemSize = 30.0 + self.itemSpacing = 20.0 + self.sideInset = sideInset + self.itemCount = itemCount + + self.contentSize = CGSize(width: self.sideInset * 2.0 + CGFloat(self.itemCount) * self.itemSize + CGFloat(self.itemCount - 1) * self.itemSpacing, height: height) + } + + func frame(at index: Int) -> CGRect { + return CGRect(origin: CGPoint(x: sideInset + CGFloat(index) * (self.itemSize + self.itemSpacing), y: floor((self.contentSize.height - self.itemSize) / 2.0)), size: CGSize(width: self.itemSize, height: self.itemSize)) + } + + func visibleItems(for rect: CGRect) -> Range? { + let offsetRect = rect.offsetBy(dx: -self.sideInset, dy: 0.0) + var minVisibleIndex = Int(floor((offsetRect.minX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + minVisibleIndex = max(0, minVisibleIndex) + var maxVisibleIndex = Int(ceil((offsetRect.maxX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + maxVisibleIndex = min(maxVisibleIndex, self.itemCount - 1) + + if minVisibleIndex <= maxVisibleIndex { + return minVisibleIndex ..< (maxVisibleIndex + 1) + } else { + return nil + } + } + } + + private let performItemAction: (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void + + private var visibleItemLayers: [EmojiPagerContentComponent.View.ItemLayer.Key: EmojiPagerContentComponent.View.ItemLayer] = [:] + private var ignoreScrolling: Bool = false + + private var context: AccountContext? + private var theme: PresentationTheme? + private var cache: AnimationCache? + private var renderer: MultiAnimationRenderer? + private var currentInsets: UIEdgeInsets? + private var currentSize: CGSize? + private var items: [EmojiPagerContentComponent.Item]? + + private var itemLayout: ItemLayout? + + init(performItemAction: @escaping (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void) { + self.performItemAction = performItemAction + + super.init(frame: CGRect()) + + self.delaysContentTouches = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.contentInsetAdjustmentBehavior = .never + } + if #available(iOS 13.0, *) { + self.automaticallyAdjustsScrollIndicatorInsets = false + } + self.showsVerticalScrollIndicator = true + self.showsHorizontalScrollIndicator = false + self.delegate = self + self.clipsToBounds = true + self.scrollsToTop = false + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func tapGesture(_ recognizer: UITapGestureRecognizer) -> Bool { + guard let itemLayout = self.itemLayout else { + return false + } + + if case .ended = recognizer.state { + let point = recognizer.location(in: self) + for (_, itemLayer) in self.visibleItemLayers { + if itemLayer.frame.inset(by: UIEdgeInsets(top: 6.0, left: itemLayout.itemSpacing, bottom: 6.0, right: itemLayout.itemSpacing)).contains(point) { + self.performItemAction(itemLayer.item, self, itemLayer.frame, itemLayer) + return true + } + } + } + + return false + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if !self.ignoreScrolling { + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoad: false) + } + } + + private func updateVisibleItems(transition: Transition, attemptSynchronousLoad: Bool) { + guard let context = self.context, let itemLayout = self.itemLayout, let items = self.items, let cache = self.cache, let renderer = self.renderer else { + return + } + + var validIds = Set() + if let itemRange = itemLayout.visibleItems(for: self.bounds) { + for index in itemRange.lowerBound ..< itemRange.upperBound { + let item = items[index] + let itemId = EmojiPagerContentComponent.View.ItemLayer.Key(groupId: AnyHashable(0), fileId: item.file?.fileId, staticEmoji: item.staticEmoji) + validIds.insert(itemId) + + let itemLayer: EmojiPagerContentComponent.View.ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + itemLayer = EmojiPagerContentComponent.View.ItemLayer( + item: item, + context: context, + attemptSynchronousLoad: attemptSynchronousLoad, + file: item.file, + staticEmoji: item.staticEmoji, + cache: cache, + renderer: renderer, + placeholderColor: .clear, + blurredBadgeColor: .clear, + pointSize: CGSize(width: 32.0, height: 32.0), + onUpdateDisplayPlaceholder: { _, _ in + } + ) + self.visibleItemLayers[itemId] = itemLayer + self.layer.addSublayer(itemLayer) + } + + let itemFrame = itemLayout.frame(at: index) + itemLayer.frame = itemFrame + + itemLayer.isVisibleForAnimations = true + } + } + + var removedIds: [EmojiPagerContentComponent.View.ItemLayer.Key] = [] + for (id, itemLayer) in self.visibleItemLayers { + if !validIds.contains(id) { + removedIds.append(id) + itemLayer.removeFromSuperlayer() + } + } + for id in removedIds { + self.visibleItemLayers.removeValue(forKey: id) + } + } + + func update( + context: AccountContext, + theme: PresentationTheme, + insets: UIEdgeInsets, + size: CGSize, + items: [EmojiPagerContentComponent.Item], + cache: AnimationCache, + renderer: MultiAnimationRenderer, + attemptSynchronousLoad: Bool + ) { + if self.theme === theme && self.currentInsets == insets && self.currentSize == size && self.items == items { + return + } + + self.context = context + self.theme = theme + self.currentInsets = insets + self.currentSize = size + self.items = items + self.cache = cache + self.renderer = renderer + + let itemLayout = ItemLayout(height: size.height, sideInset: insets.left, itemCount: items.count) + self.itemLayout = itemLayout + + self.ignoreScrolling = true + if itemLayout.contentSize != self.contentSize { + self.contentSize = itemLayout.contentSize + } + self.ignoreScrolling = false + + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoad: attemptSynchronousLoad) + } +} + +private final class GroupExpandActionButton: UIButton { + override static var layerClass: AnyClass { + return PassthroughLayer.self + } + + let tintContainerLayer: SimpleLayer + + private var currentTextLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? + private let backgroundLayer: SimpleLayer + private let tintBackgroundLayer: SimpleLayer + private let textLayer: SimpleLayer + private let pressed: () -> Void + + init(pressed: @escaping () -> Void) { + self.pressed = pressed + + self.tintContainerLayer = SimpleLayer() + + self.backgroundLayer = SimpleLayer() + self.backgroundLayer.masksToBounds = true + + self.tintBackgroundLayer = SimpleLayer() + self.tintBackgroundLayer.masksToBounds = true + + self.textLayer = SimpleLayer() + + super.init(frame: CGRect()) + + (self.layer as? PassthroughLayer)?.mirrorLayer = self.tintContainerLayer + + self.layer.addSublayer(self.backgroundLayer) + + self.layer.addSublayer(self.textLayer) + + self.addTarget(self, action: #selector(self.onPressed), for: .touchUpInside) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + @objc private func onPressed() { + self.pressed() + } + + override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool { + self.alpha = 0.6 + + return super.beginTracking(touch, with: event) + } + + override func endTracking(_ touch: UITouch?, with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.endTracking(touch, with: event) + } + + override func cancelTracking(with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.cancelTracking(with: event) + } + + override func touchesCancelled(_ touches: Set, with event: UIEvent?) { + let alpha = self.alpha + self.alpha = 1.0 + self.layer.animateAlpha(from: alpha, to: 1.0, duration: 0.25) + + super.touchesCancelled(touches, with: event) + } + + func update(theme: PresentationTheme, title: String) -> CGSize { + let textConstrainedWidth: CGFloat = 100.0 + let color = theme.list.itemCheckColors.foregroundColor + + self.backgroundLayer.backgroundColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor + self.tintContainerLayer.backgroundColor = UIColor.white.cgColor + + let textSize: CGSize + if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == textConstrainedWidth { + textSize = currentTextLayout.size + } else { + let font: UIFont = Font.semibold(13.0) + let string = NSAttributedString(string: title.uppercased(), font: font, textColor: color) + let stringBounds = string.boundingRect(with: CGSize(width: textConstrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + textSize = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) + self.textLayer.contents = generateImage(textSize, opaque: false, scale: 0.0, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + + string.draw(in: stringBounds) + + UIGraphicsPopContext() + })?.cgImage + self.currentTextLayout = (title, color, textConstrainedWidth, textSize) + } + + var sideInset: CGFloat = 10.0 + if textSize.width > 24.0 { + sideInset = 6.0 + } + let size = CGSize(width: textSize.width + sideInset * 2.0, height: 28.0) + + let textFrame = CGRect(origin: CGPoint(x: floor((size.width - textSize.width) / 2.0), y: floor((size.height - textSize.height) / 2.0)), size: textSize) + self.textLayer.frame = textFrame + + self.backgroundLayer.frame = CGRect(origin: CGPoint(), size: size) + self.tintBackgroundLayer.frame = CGRect(origin: CGPoint(), size: size) + self.backgroundLayer.cornerRadius = min(size.width, size.height) / 2.0 + self.tintContainerLayer.cornerRadius = min(size.width, size.height) / 2.0 + + return size + } +} + +public final class EmojiPagerContentComponent: Component { + public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) + + public final class ContentAnimation { + public enum AnimationType { + case generic + case groupExpanded(id: AnyHashable) + case groupInstalled(id: AnyHashable) + } + + public let type: AnimationType + + public init(type: AnimationType) { + self.type = type + } + } + + public final class InputInteractionHolder { + public var inputInteraction: InputInteraction? + + public init() { + } + } + + public final class InputInteraction { + public let performItemAction: (AnyHashable, Item, UIView, CGRect, CALayer) -> Void + public let deleteBackwards: () -> Void + public let openStickerSettings: () -> Void + public let openFeatured: () -> Void + public let addGroupAction: (AnyHashable, Bool) -> Void + public let clearGroup: (AnyHashable) -> Void + public let pushController: (ViewController) -> Void + public let presentController: (ViewController) -> Void + public let presentGlobalOverlayController: (ViewController) -> Void + public let navigationController: () -> NavigationController? + public let sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Void)? + public let chatPeerId: PeerId? + + public init( + performItemAction: @escaping (AnyHashable, Item, UIView, CGRect, CALayer) -> Void, + deleteBackwards: @escaping () -> Void, + openStickerSettings: @escaping () -> Void, + openFeatured: @escaping () -> Void, + addGroupAction: @escaping (AnyHashable, Bool) -> Void, + clearGroup: @escaping (AnyHashable) -> Void, + pushController: @escaping (ViewController) -> Void, + presentController: @escaping (ViewController) -> Void, + presentGlobalOverlayController: @escaping (ViewController) -> Void, + navigationController: @escaping () -> NavigationController?, + sendSticker: ((FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Void)?, + chatPeerId: PeerId? + ) { + self.performItemAction = performItemAction + self.deleteBackwards = deleteBackwards + self.openStickerSettings = openStickerSettings + self.openFeatured = openFeatured + self.addGroupAction = addGroupAction + self.clearGroup = clearGroup + self.pushController = pushController + self.presentController = presentController + self.presentGlobalOverlayController = presentGlobalOverlayController + self.navigationController = navigationController + self.sendSticker = sendSticker + self.chatPeerId = chatPeerId + } + } + + public enum StaticEmojiSegment: Int32, CaseIterable { + case people = 0 + case animalsAndNature = 1 + case foodAndDrink = 2 + case activityAndSport = 3 + case travelAndPlaces = 4 + case objects = 5 + case symbols = 6 + case flags = 7 + } + + public final class Item: Equatable { + public let file: TelegramMediaFile? + public let staticEmoji: String? + public let subgroupId: Int32? + + public init( + file: TelegramMediaFile?, + staticEmoji: String?, + subgroupId: Int32? + ) { + self.file = file + self.staticEmoji = staticEmoji + self.subgroupId = subgroupId + } + + public static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs === rhs { + return true + } + if lhs.file?.fileId != rhs.file?.fileId { + return false + } + if lhs.staticEmoji != rhs.staticEmoji { + return false + } + if lhs.subgroupId != rhs.subgroupId { + return false + } + + return true + } + } + + public final class ItemGroup: Equatable { + public let supergroupId: AnyHashable + public let groupId: AnyHashable + public let title: String? + public let subtitle: String? + public let actionButtonTitle: String? + public let isFeatured: Bool + public let isPremiumLocked: Bool + public let isEmbedded: Bool + public let hasClear: Bool + public let isExpandable: Bool + public let displayPremiumBadges: Bool + public let items: [Item] + + public init( + supergroupId: AnyHashable, + groupId: AnyHashable, + title: String?, + subtitle: String?, + actionButtonTitle: String?, + isFeatured: Bool, + isPremiumLocked: Bool, + isEmbedded: Bool, + hasClear: Bool, + isExpandable: Bool, + displayPremiumBadges: Bool, + items: [Item] + ) { + self.supergroupId = supergroupId + self.groupId = groupId + self.title = title + self.subtitle = subtitle + self.actionButtonTitle = actionButtonTitle + self.isFeatured = isFeatured + self.isPremiumLocked = isPremiumLocked + self.isEmbedded = isEmbedded + self.hasClear = hasClear + self.isExpandable = isExpandable + self.displayPremiumBadges = displayPremiumBadges + self.items = items + } + + public static func ==(lhs: ItemGroup, rhs: ItemGroup) -> Bool { + if lhs === rhs { + return true + } + if lhs.supergroupId != rhs.supergroupId { + return false + } + if lhs.groupId != rhs.groupId { + return false + } + if lhs.title != rhs.title { + return false + } + if lhs.subtitle != rhs.subtitle { + return false + } + if lhs.actionButtonTitle != rhs.actionButtonTitle { + return false + } + if lhs.isFeatured != rhs.isFeatured { + return false + } + if lhs.isPremiumLocked != rhs.isPremiumLocked { + return false + } + if lhs.isEmbedded != rhs.isEmbedded { + return false + } + if lhs.hasClear != rhs.hasClear { + return false + } + if lhs.isExpandable != rhs.isExpandable { + return false + } + if lhs.displayPremiumBadges != rhs.displayPremiumBadges { + return false + } + if lhs.items != rhs.items { + return false + } + return true + } + } + + public enum ItemLayoutType { + case compact + case detailed + } + + public let id: AnyHashable + public let context: AccountContext + public let animationCache: AnimationCache + public let animationRenderer: MultiAnimationRenderer + public let inputInteractionHolder: InputInteractionHolder + public let itemGroups: [ItemGroup] + public let itemLayoutType: ItemLayoutType + + public init( + id: AnyHashable, + context: AccountContext, + animationCache: AnimationCache, + animationRenderer: MultiAnimationRenderer, + inputInteractionHolder: InputInteractionHolder, + itemGroups: [ItemGroup], + itemLayoutType: ItemLayoutType + ) { + self.id = id + self.context = context + self.animationCache = animationCache + self.animationRenderer = animationRenderer + self.inputInteractionHolder = inputInteractionHolder + self.itemGroups = itemGroups + self.itemLayoutType = itemLayoutType + } + + public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool { + if lhs === rhs { + return true + } + if lhs.id != rhs.id { + return false + } + if lhs.context !== rhs.context { + return false + } + if lhs.animationCache !== rhs.animationCache { + return false + } + if lhs.animationRenderer !== rhs.animationRenderer { + return false + } + if lhs.inputInteractionHolder !== rhs.inputInteractionHolder { + return false + } + if lhs.itemGroups != rhs.itemGroups { + return false + } + if lhs.itemLayoutType != rhs.itemLayoutType { + return false + } + + return true + } + + public final class Tag { + public let id: AnyHashable + + public init(id: AnyHashable) { + self.id = id + } + } + + public final class View: UIView, UIScrollViewDelegate, PagerContentViewWithBackground, ComponentTaggedView { + private struct ItemGroupDescription: Equatable { + let supergroupId: AnyHashable + let groupId: AnyHashable + let hasTitle: Bool + let isPremiumLocked: Bool + let isFeatured: Bool + let itemCount: Int + let isEmbedded: Bool + let isExpandable: Bool + } + + private struct ItemGroupLayout: Equatable { + let frame: CGRect + let supergroupId: AnyHashable + let groupId: AnyHashable + let headerHeight: CGFloat + let itemTopOffset: CGFloat + let itemCount: Int + let collapsedItemIndex: Int? + let collapsedItemText: String? + } + + private struct ItemLayout: Equatable { + var layoutType: ItemLayoutType + var width: CGFloat + var headerInsets: UIEdgeInsets + var itemInsets: UIEdgeInsets + var itemGroupLayouts: [ItemGroupLayout] + var itemDefaultHeaderHeight: CGFloat + var itemFeaturedHeaderHeight: CGFloat + var nativeItemSize: CGFloat + let visibleItemSize: CGFloat + let playbackItemSize: CGFloat + var horizontalSpacing: CGFloat + var verticalSpacing: CGFloat + var verticalGroupDefaultSpacing: CGFloat + var verticalGroupFeaturedSpacing: CGFloat + var itemsPerRow: Int + var contentSize: CGSize + + var premiumButtonInset: CGFloat + var premiumButtonHeight: CGFloat + + init(layoutType: ItemLayoutType, width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], expandedGroupIds: Set) { + self.layoutType = layoutType + self.width = width + + self.premiumButtonInset = 6.0 + self.premiumButtonHeight = 50.0 + + let minItemsPerRow: Int + let minSpacing: CGFloat + switch layoutType { + case .compact: + minItemsPerRow = 8 + self.nativeItemSize = 40.0 + self.playbackItemSize = 48.0 + self.verticalSpacing = 9.0 + + if width >= 420.0 { + self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 5.0, bottom: containerInsets.bottom, right: containerInsets.right + 5.0) + minSpacing = 2.0 + } else { + self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 7.0, bottom: containerInsets.bottom, right: containerInsets.right + 7.0) + minSpacing = 9.0 + } + + self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 16.0, bottom: containerInsets.bottom, right: containerInsets.right + 16.0) + + self.itemDefaultHeaderHeight = 24.0 + self.itemFeaturedHeaderHeight = self.itemDefaultHeaderHeight + case .detailed: + minItemsPerRow = 5 + self.nativeItemSize = 70.0 + self.playbackItemSize = 96.0 + self.verticalSpacing = 2.0 + minSpacing = 12.0 + self.itemDefaultHeaderHeight = 24.0 + self.itemFeaturedHeaderHeight = 60.0 + self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 10.0, bottom: containerInsets.bottom, right: containerInsets.right + 10.0) + self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 16.0, bottom: containerInsets.bottom, right: containerInsets.right + 16.0) + } + + self.verticalGroupDefaultSpacing = 18.0 + self.verticalGroupFeaturedSpacing = 15.0 + + let itemHorizontalSpace = width - self.itemInsets.left - self.itemInsets.right + + self.itemsPerRow = max(minItemsPerRow, Int((itemHorizontalSpace + minSpacing) / (self.nativeItemSize + minSpacing))) + + self.visibleItemSize = self.nativeItemSize + + self.horizontalSpacing = floorToScreenPixels((itemHorizontalSpace - self.visibleItemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) + + let actualContentWidth = self.visibleItemSize * CGFloat(self.itemsPerRow) + self.horizontalSpacing * CGFloat(self.itemsPerRow - 1) + self.itemInsets.left = floorToScreenPixels((width - actualContentWidth) / 2.0) + self.itemInsets.right = self.itemInsets.left + + var verticalGroupOrigin: CGFloat = self.itemInsets.top + self.itemGroupLayouts = [] + for itemGroup in itemGroups { + var itemTopOffset: CGFloat = 0.0 + var headerHeight: CGFloat = 0.0 + var groupSpacing = self.verticalGroupDefaultSpacing + if itemGroup.hasTitle { + if itemGroup.isFeatured { + headerHeight = self.itemFeaturedHeaderHeight + groupSpacing = self.verticalGroupFeaturedSpacing + } else { + headerHeight = self.itemDefaultHeaderHeight + } + } + if itemGroup.isEmbedded { + headerHeight += 32.0 + groupSpacing -= 4.0 + } + itemTopOffset += headerHeight + + var numRowsInGroup: Int + if itemGroup.isEmbedded { + numRowsInGroup = 0 + } else { + numRowsInGroup = (itemGroup.itemCount + (self.itemsPerRow - 1)) / self.itemsPerRow + } + + var collapsedItemIndex: Int? + var collapsedItemText: String? + let visibleItemCount: Int + if itemGroup.isEmbedded { + visibleItemCount = 0 + } else if itemGroup.isExpandable && !expandedGroupIds.contains(itemGroup.groupId) { + let maxLines: Int + #if DEBUG + maxLines = 2 + #else + maxLines = 3 + #endif + if numRowsInGroup > maxLines { + visibleItemCount = self.itemsPerRow * maxLines - 1 + collapsedItemIndex = visibleItemCount + collapsedItemText = "+\(itemGroup.itemCount - visibleItemCount)" + } else { + visibleItemCount = itemGroup.itemCount + } + } else { + visibleItemCount = itemGroup.itemCount + } + + if !itemGroup.isEmbedded { + numRowsInGroup = (visibleItemCount + (self.itemsPerRow - 1)) / self.itemsPerRow + } + + var groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.visibleItemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + if (itemGroup.isPremiumLocked || itemGroup.isFeatured), case .compact = layoutType { + groupContentSize.height += self.premiumButtonInset + self.premiumButtonHeight + } + + self.itemGroupLayouts.append(ItemGroupLayout( + frame: CGRect(origin: CGPoint(x: 0.0, y: verticalGroupOrigin), size: groupContentSize), + supergroupId: itemGroup.supergroupId, + groupId: itemGroup.groupId, + headerHeight: headerHeight, + itemTopOffset: itemTopOffset, + itemCount: visibleItemCount, + collapsedItemIndex: collapsedItemIndex, + collapsedItemText: collapsedItemText + )) + verticalGroupOrigin += groupContentSize.height + groupSpacing + } + verticalGroupOrigin += self.itemInsets.bottom + self.contentSize = CGSize(width: width, height: verticalGroupOrigin) + } + + func frame(groupIndex: Int, itemIndex: Int) -> CGRect { + let groupLayout = self.itemGroupLayouts[groupIndex] + + let row = itemIndex / self.itemsPerRow + let column = itemIndex % self.itemsPerRow + + return CGRect( + origin: CGPoint( + x: self.itemInsets.left + CGFloat(column) * (self.visibleItemSize + self.horizontalSpacing), + y: groupLayout.frame.minY + groupLayout.itemTopOffset + CGFloat(row) * (self.visibleItemSize + self.verticalSpacing) + ), + size: CGSize( + width: self.visibleItemSize, + height: self.visibleItemSize + ) + ) + } + + func visibleItems(for rect: CGRect) -> [(supergroupId: AnyHashable, groupId: AnyHashable, groupIndex: Int, groupItems: Range?)] { + var result: [(supergroupId: AnyHashable, groupId: AnyHashable, groupIndex: Int, groupItems: Range?)] = [] + + for groupIndex in 0 ..< self.itemGroupLayouts.count { + let group = self.itemGroupLayouts[groupIndex] + + if !rect.intersects(group.frame) { + continue + } + let offsetRect = rect.offsetBy(dx: -self.itemInsets.left, dy: -group.frame.minY - group.itemTopOffset) + var minVisibleRow = Int(floor((offsetRect.minY - self.verticalSpacing) / (self.visibleItemSize + self.verticalSpacing))) + minVisibleRow = max(0, minVisibleRow) + let maxVisibleRow = Int(ceil((offsetRect.maxY - self.verticalSpacing) / (self.visibleItemSize + self.verticalSpacing))) + + let minVisibleIndex = minVisibleRow * self.itemsPerRow + let maxVisibleIndex = min(group.itemCount - 1, (maxVisibleRow + 1) * self.itemsPerRow - 1) + + result.append(( + supergroupId: group.supergroupId, + groupId: group.groupId, + groupIndex: groupIndex, + groupItems: maxVisibleIndex >= minVisibleIndex ? (minVisibleIndex ..< (maxVisibleIndex + 1)) : nil + )) + } + + return result + } + } + + public final class ItemPlaceholderView: UIView { + private let shimmerView: PortalSourceView? + private var placeholderView: PortalView? + private let placeholderMaskLayer: SimpleLayer + private var placeholderImageView: UIImageView? + + public init( + context: AccountContext, + file: TelegramMediaFile, + shimmerView: PortalSourceView?, + color: UIColor, + size: CGSize + ) { + self.shimmerView = shimmerView + self.placeholderMaskLayer = SimpleLayer() + + super.init(frame: CGRect()) + + if let shimmerView = self.shimmerView, let placeholderView = PortalView() { + self.placeholderView = placeholderView + + placeholderView.view.clipsToBounds = true + placeholderView.view.layer.mask = self.placeholderMaskLayer + self.addSubview(placeholderView.view) + shimmerView.addPortal(view: placeholderView) + } + + let useDirectContent = self.placeholderView == nil + Queue.concurrentDefaultQueue().async { [weak self] in + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, scale: min(2.0, UIScreenScale), imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: useDirectContent ? color : .black) { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + if useDirectContent { + strongSelf.layer.contents = image.cgImage + } else { + strongSelf.placeholderMaskLayer.contents = image.cgImage + } + } + } + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func update(size: CGSize) { + if let placeholderView = self.placeholderView { + placeholderView.view.frame = CGRect(origin: CGPoint(), size: size) + } + self.placeholderMaskLayer.frame = CGRect(origin: CGPoint(), size: size) + } + } + + public final class ItemLayer: MultiAnimationRenderTarget { + public struct Key: Hashable { + var groupId: AnyHashable + var fileId: MediaId? + var staticEmoji: String? + + public init( + groupId: AnyHashable, + fileId: MediaId?, + staticEmoji: String? + ) { + self.groupId = groupId + self.fileId = fileId + self.staticEmoji = staticEmoji + } + } + + enum Badge { + case premium + case locked + case featured + } + + let item: Item + + private let file: TelegramMediaFile? + private let staticEmoji: String? + private let placeholderColor: UIColor + private let size: CGSize + private var disposable: Disposable? + private var fetchDisposable: Disposable? + private var premiumBadgeView: PremiumBadgeView? + + private var badge: Badge? + private var validSize: CGSize? + + private var isInHierarchyValue: Bool = false + public var isVisibleForAnimations: Bool = false { + didSet { + if self.isVisibleForAnimations != oldValue { + self.updatePlayback() + } + } + } + public private(set) var displayPlaceholder: Bool = false + public let onUpdateDisplayPlaceholder: (Bool, Double) -> Void + + public init( + item: Item, + context: AccountContext, + attemptSynchronousLoad: Bool, + file: TelegramMediaFile?, + staticEmoji: String?, + cache: AnimationCache, + renderer: MultiAnimationRenderer, + placeholderColor: UIColor, + blurredBadgeColor: UIColor, + pointSize: CGSize, + onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void + ) { + self.item = item + self.file = file + self.staticEmoji = staticEmoji + self.placeholderColor = placeholderColor + self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder + + let scale = min(2.0, UIScreenScale) + let pixelSize = CGSize(width: pointSize.width * scale, height: pointSize.height * scale) + self.size = CGSize(width: pixelSize.width / scale, height: pixelSize.height / scale) + + super.init() + + if let file = file { + let loadAnimation: () -> Void = { [weak self] in + guard let strongSelf = self else { + return + } + + strongSelf.disposable = renderer.add(target: strongSelf, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, fetch: { size, writer in + let source = AnimatedStickerResourceSource(account: context.account, resource: file.resource, fitzModifier: nil, isVideo: false) + + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { + return + } + + if file.isVideoEmoji || file.isVideoSticker { + cacheVideoAnimation(path: result, width: Int(size.width), height: Int(size.height), writer: writer) + } else if file.isAnimatedSticker { + guard let data = try? Data(contentsOf: URL(fileURLWithPath: result)) else { + writer.finish() + return + } + cacheLottieAnimation(data: data, width: Int(size.width), height: Int(size.height), writer: writer) + } else { + cacheStillSticker(path: result, width: Int(size.width), height: Int(size.height), writer: writer) + } + }) + + let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } + + if attemptSynchronousLoad { + if !renderer.loadFirstFrameSynchronously(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + self.updateDisplayPlaceholder(displayPlaceholder: true) + } + + loadAnimation() + } else { + let _ = renderer.loadFirstFrame(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in + loadAnimation() + + if !success { + guard let strongSelf = self else { + return + } + + strongSelf.updateDisplayPlaceholder(displayPlaceholder: true) + } + }) + } + } else if let staticEmoji = staticEmoji { + let image = generateImage(self.size, opaque: false, scale: min(UIScreenScale, 3.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + let preScaleFactor: CGFloat = 1.0 + let scaledSize = CGSize(width: floor(size.width * preScaleFactor), height: floor(size.height * preScaleFactor)) + let scaleFactor = scaledSize.width / size.width + + context.scaleBy(x: 1.0 / scaleFactor, y: 1.0 / scaleFactor) + + let string = NSAttributedString(string: staticEmoji, font: Font.regular(floor(32.0 * scaleFactor)), textColor: .black) + let boundingRect = string.boundingRect(with: scaledSize, options: .usesLineFragmentOrigin, context: nil) + UIGraphicsPushContext(context) + string.draw(at: CGPoint(x: floor((scaledSize.width - boundingRect.width) / 2.0 + boundingRect.minX), y: floor((scaledSize.height - boundingRect.height) / 2.0 + boundingRect.minY))) + UIGraphicsPopContext() + }) + self.contents = image?.cgImage + } + } + + override public init(layer: Any) { + guard let layer = layer as? ItemLayer else { + preconditionFailure() + } + + self.item = layer.item + + self.file = layer.file + self.staticEmoji = layer.staticEmoji + self.placeholderColor = layer.placeholderColor + self.size = layer.size + + self.onUpdateDisplayPlaceholder = { _, _ in } + + super.init(layer: layer) + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.disposable?.dispose() + self.fetchDisposable?.dispose() + } + + public override func action(forKey event: String) -> CAAction? { + if event == kCAOnOrderIn { + self.isInHierarchyValue = true + } else if event == kCAOnOrderOut { + self.isInHierarchyValue = false + } + self.updatePlayback() + return nullAction + } + + func update(transition: Transition, size: CGSize, badge: Badge?, blurredBadgeColor: UIColor, blurredBadgeBackgroundColor: UIColor) { + if self.badge != badge || self.validSize != size { + self.badge = badge + self.validSize = size + + if let badge = badge { + var badgeTransition = transition + let premiumBadgeView: PremiumBadgeView + if let current = self.premiumBadgeView { + premiumBadgeView = current + } else { + badgeTransition = .immediate + premiumBadgeView = PremiumBadgeView() + self.premiumBadgeView = premiumBadgeView + self.addSublayer(premiumBadgeView.layer) + } + + let badgeDiameter = min(16.0, floor(size.height * 0.5)) + let badgeSize = CGSize(width: badgeDiameter, height: badgeDiameter) + badgeTransition.setFrame(view: premiumBadgeView, frame: CGRect(origin: CGPoint(x: size.width - badgeSize.width, y: size.height - badgeSize.height), size: badgeSize)) + premiumBadgeView.update(transition: badgeTransition, badge: badge, backgroundColor: blurredBadgeColor, size: badgeSize) + + self.blurredRepresentationBackgroundColor = blurredBadgeBackgroundColor + self.blurredRepresentationTarget = premiumBadgeView.contentLayer + } else { + if let premiumBadgeView = self.premiumBadgeView { + self.premiumBadgeView = nil + premiumBadgeView.removeFromSuperview() + + self.blurredRepresentationBackgroundColor = nil + self.blurredRepresentationTarget = nil + } + } + } + } + + private func updatePlayback() { + let shouldBePlaying = self.isInHierarchyValue && self.isVisibleForAnimations + + self.shouldBeAnimating = shouldBePlaying + } + + public override func updateDisplayPlaceholder(displayPlaceholder: Bool) { + if self.displayPlaceholder == displayPlaceholder { + return + } + + self.displayPlaceholder = displayPlaceholder + self.onUpdateDisplayPlaceholder(displayPlaceholder, 0.0) + } + + public override func transitionToContents(_ contents: AnyObject) { + self.contents = contents + + if self.displayPlaceholder { + self.displayPlaceholder = false + self.onUpdateDisplayPlaceholder(false, 0.2) + self.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) + } + } + } + + private final class GroupBorderLayer: PassthroughShapeLayer { + let tintContainerLayer: CAShapeLayer + + override init() { + self.tintContainerLayer = CAShapeLayer() + + super.init() + + self.mirrorLayer = self.tintContainerLayer + } + + override func action(forKey event: String) -> CAAction? { + return nullAction + } + + override init(layer: Any) { + self.tintContainerLayer = CAShapeLayer() + + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + + private final class ContentScrollLayer: CALayer { + var mirrorLayer: CALayer? + + override init() { + super.init() + } + + override init(layer: Any) { + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override var position: CGPoint { + get { + return super.position + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.position = value + } + super.position = value + } + } + + override var bounds: CGRect { + get { + return super.bounds + } set(value) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.bounds = value + } + super.bounds = value + } + } + + override func add(_ animation: CAAnimation, forKey key: String?) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.add(animation, forKey: key) + } + + super.add(animation, forKey: key) + } + + override func removeAllAnimations() { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAllAnimations() + } + + super.removeAllAnimations() + } + + override func removeAnimation(forKey: String) { + if let mirrorLayer = self.mirrorLayer { + mirrorLayer.removeAnimation(forKey: forKey) + } + + super.removeAnimation(forKey: forKey) + } + } + + private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { + override static var layerClass: AnyClass { + return ContentScrollLayer.self + } + + private let mirrorView: UIView + + init(mirrorView: UIView) { + self.mirrorView = mirrorView + + super.init(frame: CGRect()) + + (self.layer as? ContentScrollLayer)?.mirrorLayer = mirrorView.layer + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + + private let shimmerHostView: PortalSourceView? + private let standaloneShimmerEffect: StandaloneShimmerEffect? + + private let backgroundView: BlurredBackgroundView + private var vibrancyEffectView: UIVisualEffectView? + private let mirrorContentScrollView: UIView + private let scrollView: ContentScrollView + private let boundsChangeTrackerLayer = SimpleLayer() + private var effectiveVisibleSize: CGSize = CGSize() + + private let placeholdersContainerView: UIView + private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:] + private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] + private var visibleGroupHeaders: [AnyHashable: GroupHeaderLayer] = [:] + private var visibleGroupBorders: [AnyHashable: GroupBorderLayer] = [:] + private var visibleGroupPremiumButtons: [AnyHashable: ComponentView] = [:] + private var visibleGroupExpandActionButtons: [AnyHashable: GroupExpandActionButton] = [:] + private var expandedGroupIds: Set = Set() + private var ignoreScrolling: Bool = false + private var keepTopPanelVisibleUntilScrollingInput: Bool = false + + private var component: EmojiPagerContentComponent? + private weak var state: EmptyComponentState? + private var pagerEnvironment: PagerComponentChildEnvironment? + private var keyboardChildEnvironment: EntityKeyboardChildEnvironment? + private var activeItemUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>? + private var itemLayout: ItemLayout? + + private var peekRecognizer: PeekControllerGestureRecognizer? + private var currentContextGestureItemKey: ItemLayer.Key? + private weak var peekController: PeekController? + + override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: nil) + + if ProcessInfo.processInfo.processorCount > 2 { + self.shimmerHostView = PortalSourceView() + self.standaloneShimmerEffect = StandaloneShimmerEffect() + } else { + self.shimmerHostView = nil + self.standaloneShimmerEffect = nil + } + + self.mirrorContentScrollView = UIView() + self.mirrorContentScrollView.layer.anchorPoint = CGPoint() + self.mirrorContentScrollView.clipsToBounds = false + self.scrollView = ContentScrollView(mirrorView: self.mirrorContentScrollView) + self.scrollView.layer.anchorPoint = CGPoint() + + self.placeholdersContainerView = UIView() + + super.init(frame: frame) + + self.addSubview(self.backgroundView) + + if let shimmerHostView = self.shimmerHostView { + shimmerHostView.alpha = 0.0 + self.addSubview(shimmerHostView) + } + + self.boundsChangeTrackerLayer.opacity = 0.0 + self.layer.addSublayer(self.boundsChangeTrackerLayer) + self.boundsChangeTrackerLayer.didEnterHierarchy = { [weak self] in + self?.standaloneShimmerEffect?.updateLayer() + } + + self.scrollView.delaysContentTouches = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollView.contentInsetAdjustmentBehavior = .never + } + if #available(iOS 13.0, *) { + self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + self.scrollView.showsVerticalScrollIndicator = true + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.delegate = self + self.scrollView.clipsToBounds = false + self.scrollView.scrollsToTop = false + self.addSubview(self.scrollView) + + self.scrollView.addSubview(self.placeholdersContainerView) + + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + + let peekRecognizer = PeekControllerGestureRecognizer(contentAtPoint: { [weak self] point in + guard let strongSelf = self, let component = strongSelf.component else { + return nil + } + guard let item = strongSelf.item(atPoint: point), let itemLayer = strongSelf.visibleItemLayers[item.1], let file = item.0.file else { + return nil + } + if itemLayer.displayPlaceholder { + return nil + } + + let context = component.context + let accountPeerId = context.account.peerId + return combineLatest( + context.engine.stickers.isStickerSaved(id: file.fileId), + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: accountPeerId)) |> map { peer -> Bool in + var hasPremium = false + if case let .user(user) = peer, user.isPremium { + hasPremium = true + } + return hasPremium + } + ) + |> deliverOnMainQueue + |> map { [weak itemLayer] isStarred, hasPremium -> (UIView, CGRect, PeekControllerContent)? in + guard let strongSelf = self, let component = strongSelf.component, let itemLayer = itemLayer else { + return nil + } + var menuItems: [ContextMenuItem] = [] + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + if let inputInteraction = component.inputInteractionHolder.inputInteraction, let sendSticker = inputInteraction.sendSticker, let chatPeerId = inputInteraction.chatPeerId { + if chatPeerId != component.context.account.peerId && chatPeerId.namespace != Namespaces.Peer.SecretChat { + menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_SendSilently, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/SilentIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + if let strongSelf = self, let peekController = strongSelf.peekController { + if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { + sendSticker(.standalone(media: file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + sendSticker(.standalone(media: file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) + } + } + f(.default) + }))) + } + + menuItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + if let strongSelf = self, let peekController = strongSelf.peekController { + if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { + let _ = sendSticker(.standalone(media: file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + let _ = sendSticker(.standalone(media: file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + } + } + f(.default) + }))) + } + + menuItems.append( + .action(ContextMenuActionItem(text: isStarred ? presentationData.strings.Stickers_RemoveFromFavorites : presentationData.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { _, f in + f(.default) + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let _ = (context.engine.stickers.toggleStickerSaved(file: file, saved: !isStarred) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .generic: + component.inputInteractionHolder.inputInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: !isStarred ? presentationData.strings.Conversation_StickerAddedToFavorites : presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false })) + case let .limitExceeded(limit, premiumLimit): + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let text: String + if limit == premiumLimit || premiumConfiguration.isPremiumDisabled { + text = presentationData.strings.Premium_MaxFavedStickersFinalText + } else { + text = presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string + } + component.inputInteractionHolder.inputInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { action in + if case .info = action { + let controller = PremiumIntroScreen(context: context, source: .savedStickers) + component.inputInteractionHolder.inputInteraction?.pushController(controller) + return true + } + return false + })) + } + }) + })) + ) + menuItems.append( + .action(ContextMenuActionItem(text: presentationData.strings.StickerPack_ViewPack, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Sticker"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + + loop: for attribute in file.attributes { + switch attribute { + case let .CustomEmoji(_, _, packReference), let .Sticker(_, packReference, _): + if let packReference = packReference { + let controller = context.sharedContext.makeStickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: component.inputInteractionHolder.inputInteraction?.navigationController(), sendSticker: { file, sourceView, sourceRect in + component.inputInteractionHolder.inputInteraction?.sendSticker?(file, false, false, nil, false, sourceView, sourceRect, nil) + return true + }) + + component.inputInteractionHolder.inputInteraction?.navigationController()?.view.window?.endEditing(true) + component.inputInteractionHolder.inputInteraction?.presentController(controller) + } + break loop + default: + break + } + } + })) + ) + + return (strongSelf, strongSelf.scrollView.convert(itemLayer.frame, to: strongSelf), StickerPreviewPeekContent(account: context.account, theme: presentationData.theme, strings: presentationData.strings, item: .pack(file), isLocked: file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + let controller = PremiumIntroScreen(context: context, source: .stickers) + component.inputInteractionHolder.inputInteraction?.pushController(controller) + })) + } + }, present: { [weak self] content, sourceView, sourceRect in + guard let strongSelf = self, let component = strongSelf.component else { + return nil + } + + let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) + }) + /*controller.visibilityUpdated = { [weak self] visible in + self?.previewingStickersPromise.set(visible) + self?.requestDisableStickerAnimations?(visible) + self?.simulateUpdateLayout(isVisible: !visible) + }*/ + strongSelf.peekController = controller + component.inputInteractionHolder.inputInteraction?.presentGlobalOverlayController(controller) + return controller + }, updateContent: { [weak self] content in + guard let strongSelf = self else { + return + } + + let _ = strongSelf + + /*var item: StickerPreviewPeekItem? + if let content = content as? StickerPreviewPeekContent { + item = content.item + } + strongSelf.updatePreviewingItem(item: item, animated: true)*/ + }) + self.peekRecognizer = peekRecognizer + self.addGestureRecognizer(peekRecognizer) + self.peekRecognizer?.isEnabled = false + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func matches(tag: Any) -> Bool { + if let tag = tag as? Tag { + if tag.id == self.component?.id { + return true + } + } + return false + } + + public func scrollToItemGroup(id supergroupId: AnyHashable, subgroupId: Int32?) { + guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let itemLayout = self.itemLayout else { + return + } + for groupIndex in 0 ..< itemLayout.itemGroupLayouts.count { + let group = itemLayout.itemGroupLayouts[groupIndex] + + var subgroupItemIndex: Int? + if group.supergroupId == supergroupId { + if let subgroupId = subgroupId { + inner: for itemGroup in component.itemGroups { + if itemGroup.supergroupId == supergroupId { + for i in 0 ..< itemGroup.items.count { + if itemGroup.items[i].subgroupId == subgroupId { + subgroupItemIndex = i + break + } + } + break inner + } + } + } + let wasIgnoringScrollingEvents = self.ignoreScrolling + self.ignoreScrolling = true + self.scrollView.setContentOffset(self.scrollView.contentOffset, animated: false) + + self.keepTopPanelVisibleUntilScrollingInput = true + + let anchorFrame: CGRect + if let subgroupItemIndex = subgroupItemIndex { + anchorFrame = itemLayout.frame(groupIndex: groupIndex, itemIndex: subgroupItemIndex) + } else { + anchorFrame = group.frame + } + + var scrollPosition = anchorFrame.minY + floor(-itemLayout.verticalGroupDefaultSpacing / 2.0) - pagerEnvironment.containerInsets.top + if scrollPosition > self.scrollView.contentSize.height - self.scrollView.bounds.height { + scrollPosition = self.scrollView.contentSize.height - self.scrollView.bounds.height + } + if scrollPosition < 0.0 { + scrollPosition = 0.0 + } + + let offsetDirectionSign: Double = scrollPosition < self.scrollView.bounds.minY ? -1.0 : 1.0 + + var previousVisibleLayers: [ItemLayer.Key: (CALayer, CGRect)] = [:] + for (id, layer) in self.visibleItemLayers { + previousVisibleLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + var previousVisiblePlaceholderViews: [ItemLayer.Key: (UIView, CGRect)] = [:] + for (id, view) in self.visibleItemPlaceholderViews { + previousVisiblePlaceholderViews[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + var previousVisibleGroupHeaders: [AnyHashable: (GroupHeaderLayer, CGRect)] = [:] + for (id, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { + continue + } + previousVisibleGroupHeaders[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + var previousVisibleGroupBorders: [AnyHashable: (GroupBorderLayer, CGRect)] = [:] + for (id, layer) in self.visibleGroupBorders { + previousVisibleGroupBorders[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + var previousVisibleGroupPremiumButtons: [AnyHashable: (UIView, CGRect)] = [:] + for (id, view) in self.visibleGroupPremiumButtons { + if let view = view.view { + previousVisibleGroupPremiumButtons[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + } + var previousVisibleGroupExpandActionButtons: [AnyHashable: (GroupExpandActionButton, CGRect)] = [:] + for (id, view) in self.visibleGroupExpandActionButtons { + previousVisibleGroupExpandActionButtons[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + + self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: scrollPosition), size: self.scrollView.bounds.size) + self.ignoreScrolling = wasIgnoringScrollingEvents + + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: true, previousItemPositions: nil, updatedItemPositions: nil) + + var commonItemOffset: CGFloat? + var previousVisibleBoundingRect: CGRect? + for (id, layerAndFrame) in previousVisibleLayers { + if let layer = self.visibleItemLayers[id] { + if commonItemOffset == nil { + let visibleFrame = layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = layerAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = layerAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = layerAndFrame.1 + } + } + } + + for (id, viewAndFrame) in previousVisiblePlaceholderViews { + if let view = self.visibleItemPlaceholderViews[id] { + if commonItemOffset == nil { + let visibleFrame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = viewAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = viewAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = viewAndFrame.1 + } + } + } + + for (id, layerAndFrame) in previousVisibleGroupHeaders { + if let view = self.visibleGroupHeaders[id] { + if commonItemOffset == nil, self.scrollView.bounds.intersects(view.frame) { + let visibleFrame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = layerAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = layerAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = layerAndFrame.1 + } + } + } + + /*for (id, layerAndFrame) in previousVisibleGroupBorders { + if let layer = self.visibleGroupBorders[id] { + if commonItemOffset == nil, self.scrollView.bounds.intersects(layer.frame) { + let visibleFrame = layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = layerAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = layerAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = layerAndFrame.1 + } + } + }*/ + + for (id, viewAndFrame) in previousVisibleGroupPremiumButtons { + if let view = self.visibleGroupPremiumButtons[id]?.view, self.scrollView.bounds.intersects(view.frame) { + if commonItemOffset == nil { + let visibleFrame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = viewAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = viewAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = viewAndFrame.1 + } + } + } + + for (id, viewAndFrame) in previousVisibleGroupExpandActionButtons { + if let view = self.visibleGroupExpandActionButtons[id], self.scrollView.bounds.intersects(view.frame) { + if commonItemOffset == nil { + let visibleFrame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + commonItemOffset = viewAndFrame.1.minY - visibleFrame.minY + } + break + } else { + if let previousVisibleBoundingRectValue = previousVisibleBoundingRect { + previousVisibleBoundingRect = viewAndFrame.1.union(previousVisibleBoundingRectValue) + } else { + previousVisibleBoundingRect = viewAndFrame.1 + } + } + } + + let duration = 0.4 + let timingFunction = kCAMediaTimingFunctionSpring + + if let commonItemOffset = commonItemOffset { + for (_, layer) in self.visibleItemLayers { + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleLayers { + if self.visibleItemLayers[id] != nil { + continue + } + let layer = layerAndFrame.0 + self.scrollView.layer.addSublayer(layer) + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer] _ in + layer?.removeFromSuperlayer() + }) + } + + for (_, view) in self.visibleItemPlaceholderViews { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisiblePlaceholderViews { + if self.visibleItemPlaceholderViews[id] != nil { + continue + } + let view = viewAndFrame.0 + self.placeholdersContainerView.addSubview(view) + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } + + for (_, view) in self.visibleGroupHeaders { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisibleGroupHeaders { + if self.visibleGroupHeaders[id] != nil { + continue + } + let view = viewAndFrame.0 + self.scrollView.addSubview(view) + let tintContentLayer = view.tintContentLayer + self.mirrorContentScrollView.layer.addSublayer(tintContentLayer) + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view, weak tintContentLayer] _ in + view?.removeFromSuperview() + tintContentLayer?.removeFromSuperlayer() + }) + } + + for (_, layer) in self.visibleGroupBorders { + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleGroupBorders { + if self.visibleGroupBorders[id] != nil { + continue + } + let layer = layerAndFrame.0 + self.scrollView.layer.addSublayer(layer) + let tintContainerLayer = layer.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer, weak tintContainerLayer] _ in + layer?.removeFromSuperlayer() + tintContainerLayer?.removeFromSuperlayer() + }) + } + + for (_, view) in self.visibleGroupPremiumButtons { + if let view = view.view { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + } + for (id, viewAndFrame) in previousVisibleGroupPremiumButtons { + if self.visibleGroupPremiumButtons[id] != nil { + continue + } + let view = viewAndFrame.0 + self.scrollView.addSubview(view) + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } + + for (_, view) in self.visibleGroupExpandActionButtons { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisibleGroupExpandActionButtons { + if self.visibleGroupExpandActionButtons[id] != nil { + continue + } + let view = viewAndFrame.0 + self.scrollView.addSubview(view) + let tintContainerLayer = view.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view, weak tintContainerLayer] _ in + view?.removeFromSuperview() + tintContainerLayer?.removeFromSuperlayer() + }) + } + } else if let previousVisibleBoundingRect = previousVisibleBoundingRect { + var updatedVisibleBoundingRect: CGRect? + + for (_, layer) in self.visibleItemLayers { + let frame = layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { + updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) + } else { + updatedVisibleBoundingRect = frame + } + } + for (_, view) in self.visibleItemPlaceholderViews { + let frame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { + updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) + } else { + updatedVisibleBoundingRect = frame + } + } + for (_, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { + continue + } + let frame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { + updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) + } else { + updatedVisibleBoundingRect = frame + } + } + for (_, view) in self.visibleGroupPremiumButtons { + if let view = view.view { + if !self.scrollView.bounds.intersects(view.frame) { + continue + } + + let frame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { + updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) + } else { + updatedVisibleBoundingRect = frame + } + } + } + for (_, view) in self.visibleGroupExpandActionButtons { + if !self.scrollView.bounds.intersects(view.frame) { + continue + } + + let frame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { + updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) + } else { + updatedVisibleBoundingRect = frame + } + } + + if let updatedVisibleBoundingRect = updatedVisibleBoundingRect { + var commonItemOffset = updatedVisibleBoundingRect.height * offsetDirectionSign + + if previousVisibleBoundingRect.intersects(updatedVisibleBoundingRect) { + if offsetDirectionSign < 0.0 { + commonItemOffset = previousVisibleBoundingRect.minY - updatedVisibleBoundingRect.maxY + } else { + commonItemOffset = previousVisibleBoundingRect.maxY - updatedVisibleBoundingRect.minY + } + } + + for (_, layer) in self.visibleItemLayers { + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleLayers { + if self.visibleItemLayers[id] != nil { + continue + } + let layer = layerAndFrame.0 + layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.scrollView.layer.addSublayer(layer) + layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer] _ in + layer?.removeFromSuperlayer() + }) + } + + for (_, view) in self.visibleItemPlaceholderViews { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisiblePlaceholderViews { + if self.visibleItemPlaceholderViews[id] != nil { + continue + } + let view = viewAndFrame.0 + view.frame = viewAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.placeholdersContainerView.addSubview(view) + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } + + for (_, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { + continue + } + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisibleGroupHeaders { + if self.visibleGroupHeaders[id] != nil { + continue + } + let view = viewAndFrame.0 + view.frame = viewAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.scrollView.addSubview(view) + let tintContentLayer = view.tintContentLayer + self.mirrorContentScrollView.layer.addSublayer(tintContentLayer) + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view, weak tintContentLayer] _ in + view?.removeFromSuperview() + tintContentLayer?.removeFromSuperlayer() + }) + } + + for (_, layer) in self.visibleGroupBorders { + if !self.scrollView.bounds.intersects(layer.frame) { + continue + } + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleGroupBorders { + if self.visibleGroupBorders[id] != nil { + continue + } + let layer = layerAndFrame.0 + layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.scrollView.layer.addSublayer(layer) + let tintContainerLayer = layer.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer, weak tintContainerLayer] _ in + layer?.removeFromSuperlayer() + tintContainerLayer?.removeFromSuperlayer() + }) + } + + for (_, view) in self.visibleGroupPremiumButtons { + if let view = view.view { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + } + for (id, viewAndFrame) in previousVisibleGroupPremiumButtons { + if self.visibleGroupPremiumButtons[id] != nil { + continue + } + let view = viewAndFrame.0 + view.frame = viewAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.scrollView.addSubview(view) + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } + + for (_, view) in self.visibleGroupExpandActionButtons { + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, viewAndFrame) in previousVisibleGroupExpandActionButtons { + if self.visibleGroupExpandActionButtons[id] != nil { + continue + } + let view = viewAndFrame.0 + view.frame = viewAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) + self.scrollView.addSubview(view) + let tintContainerLayer = view.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + view.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak view, weak tintContainerLayer] _ in + view?.removeFromSuperview() + tintContainerLayer?.removeFromSuperlayer() + }) + } + } + } + } + } + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + guard let component = self.component else { + return + } + if case .ended = recognizer.state { + let locationInScrollView = recognizer.location(in: self.scrollView) + outer: for (id, groupHeader) in self.visibleGroupHeaders { + if groupHeader.frame.insetBy(dx: -10.0, dy: -6.0).contains(locationInScrollView) { + let groupHeaderPoint = self.scrollView.convert(locationInScrollView, to: groupHeader) + if let clearIconLayer = groupHeader.clearIconLayer, clearIconLayer.frame.insetBy(dx: -4.0, dy: -4.0).contains(groupHeaderPoint) { + component.inputInteractionHolder.inputInteraction?.clearGroup(id) + return + } else { + if groupHeader.tapGesture(recognizer) { + return + } + } + } + } + + var foundItem = false + var foundExactItem = false + if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { + foundExactItem = true + foundItem = true + if !itemLayer.displayPlaceholder { + component.inputInteractionHolder.inputInteraction?.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + } + } + + if !foundExactItem { + if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self), extendedHitRange: true), let itemLayer = self.visibleItemLayers[itemKey] { + foundItem = true + if !itemLayer.displayPlaceholder { + component.inputInteractionHolder.inputInteraction?.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + } + } + } + + let _ = foundItem + } + } + + private func item(atPoint point: CGPoint, extendedHitRange: Bool = false) -> (Item, ItemLayer.Key)? { + let localPoint = self.convert(point, to: self.scrollView) + + var closestItem: (key: ItemLayer.Key, distance: CGFloat)? + + for (key, itemLayer) in self.visibleItemLayers { + if extendedHitRange { + let position = CGPoint(x: itemLayer.frame.midX, y: itemLayer.frame.midY) + let distance = CGPoint(x: localPoint.x - position.x, y: localPoint.y - position.y) + let distance2 = distance.x * distance.x + distance.y * distance.y + if distance2 > pow(max(itemLayer.bounds.width, itemLayer.bounds.height), 2.0) { + continue + } + + if let closestItemValue = closestItem { + if closestItemValue.distance > distance2 { + closestItem = (key, distance2) + } + } else { + closestItem = (key, distance2) + } + } else { + if itemLayer.frame.contains(localPoint) { + return (itemLayer.item, key) + } + } + } + + if let key = closestItem?.key { + if let itemLayer = self.visibleItemLayers[key] { + return (itemLayer.item, key) + } + } + + return nil + } + + private struct ScrollingOffsetState: Equatable { + var value: CGFloat + var isDraggingOrDecelerating: Bool + } + + private var previousScrollingOffset: ScrollingOffsetState? + + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + if self.keepTopPanelVisibleUntilScrollingInput { + self.keepTopPanelVisibleUntilScrollingInput = false + + self.updateScrollingOffset(isReset: true, transition: .immediate) + } + if let presentation = scrollView.layer.presentation() { + scrollView.bounds = presentation.bounds + scrollView.layer.removeAllAnimations() + } + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false, previousItemPositions: nil, updatedItemPositions: nil) + + self.updateScrollingOffset(isReset: false, transition: .immediate) + } + + public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + if velocity.y != 0.0 { + targetContentOffset.pointee.y = self.snappedContentOffset(proposedOffset: targetContentOffset.pointee.y) + } + } + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if !decelerate { + self.snapScrollingOffsetToInsets() + } + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + self.snapScrollingOffsetToInsets() + } + + private func updateScrollingOffset(isReset: Bool, transition: Transition) { + guard let component = self.component else { + return + } + + let isInteracting = scrollView.isDragging || scrollView.isDecelerating + if let previousScrollingOffsetValue = self.previousScrollingOffset, !self.keepTopPanelVisibleUntilScrollingInput { + let currentBounds = scrollView.bounds + let offsetToTopEdge = max(0.0, currentBounds.minY - 0.0) + let offsetToBottomEdge = max(0.0, scrollView.contentSize.height - currentBounds.maxY) + + let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue.value + if case .detailed = component.itemLayoutType { + self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( + relativeOffset: relativeOffset, + absoluteOffsetToTopEdge: offsetToTopEdge, + absoluteOffsetToBottomEdge: offsetToBottomEdge, + isReset: isReset, + isInteracting: isInteracting, + transition: transition + )) + } + } + self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: isInteracting) + } + + private func snappedContentOffset(proposedOffset: CGFloat) -> CGFloat { + guard let pagerEnvironment = self.pagerEnvironment else { + return proposedOffset + } + + var proposedOffset = proposedOffset + let bounds = self.bounds + if proposedOffset + bounds.height > self.scrollView.contentSize.height - pagerEnvironment.containerInsets.bottom { + proposedOffset = self.scrollView.contentSize.height - bounds.height + } + if proposedOffset < pagerEnvironment.containerInsets.top { + proposedOffset = 0.0 + } + + return proposedOffset + } + + private func snapScrollingOffsetToInsets() { + let transition = Transition(animation: .curve(duration: 0.4, curve: .spring)) + + var currentBounds = self.scrollView.bounds + currentBounds.origin.y = self.snappedContentOffset(proposedOffset: currentBounds.minY) + transition.setBounds(view: self.scrollView, bounds: currentBounds) + + self.updateScrollingOffset(isReset: false, transition: transition) + } + + private func updateVisibleItems(transition: Transition, attemptSynchronousLoads: Bool, previousItemPositions: [ItemLayer.Key: CGPoint]?, updatedItemPositions: [ItemLayer.Key: CGPoint]?) { + guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let keyboardChildEnvironment = self.keyboardChildEnvironment, let itemLayout = self.itemLayout else { + return + } + + var topVisibleGroupId: AnyHashable? + var topVisibleSubgroupId: AnyHashable? + + var validIds = Set() + var validGroupHeaderIds = Set() + var validGroupBorderIds = Set() + var validGroupPremiumButtonIds = Set() + var validGroupExpandActionButtons = Set() + + let effectiveVisibleBounds = CGRect(origin: self.scrollView.bounds.origin, size: self.effectiveVisibleSize) + let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: pagerEnvironment.containerInsets.top) + + let contentAnimation = transition.userData(ContentAnimation.self) + var transitionHintInstalledGroupId: AnyHashable? + var transitionHintExpandedGroupId: AnyHashable? + if let contentAnimation = contentAnimation { + switch contentAnimation.type { + case let .groupInstalled(groupId): + transitionHintInstalledGroupId = groupId + case let .groupExpanded(groupId): + transitionHintExpandedGroupId = groupId + default: + break + } + } + + for groupItems in itemLayout.visibleItems(for: effectiveVisibleBounds) { + let itemGroup = component.itemGroups[groupItems.groupIndex] + let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] + + var assignTopVisibleSubgroupId = false + if topVisibleGroupId == nil && itemGroupLayout.frame.intersects(topVisibleDetectionBounds) { + topVisibleGroupId = groupItems.supergroupId + assignTopVisibleSubgroupId = true + } + + var headerCentralContentWidth: CGFloat? + var headerSizeUpdated = false + if let title = itemGroup.title { + validGroupHeaderIds.insert(itemGroup.groupId) + let groupHeaderView: GroupHeaderLayer + var groupHeaderTransition = transition + if let current = self.visibleGroupHeaders[itemGroup.groupId] { + groupHeaderView = current + } else { + groupHeaderTransition = .immediate + let groupId = itemGroup.groupId + groupHeaderView = GroupHeaderLayer( + actionPressed: { [weak self] in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteractionHolder.inputInteraction?.addGroupAction(groupId, false) + }, + performItemAction: { [weak self] item, view, rect, layer in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteractionHolder.inputInteraction?.performItemAction(groupId, item, view, rect, layer) + } + ) + self.visibleGroupHeaders[itemGroup.groupId] = groupHeaderView + self.scrollView.addSubview(groupHeaderView) + self.mirrorContentScrollView.layer.addSublayer(groupHeaderView.tintContentLayer) + } + + var actionButtonTitle: String? + if case .detailed = itemLayout.layoutType, itemGroup.isFeatured { + actionButtonTitle = itemGroup.actionButtonTitle + } + + let hasTopSeparator = false + + let (groupHeaderSize, centralContentWidth) = groupHeaderView.update( + context: component.context, + theme: keyboardChildEnvironment.theme, + layoutType: itemLayout.layoutType, + hasTopSeparator: hasTopSeparator, + actionButtonTitle: actionButtonTitle, + title: title, + subtitle: itemGroup.subtitle, + isPremiumLocked: itemGroup.isPremiumLocked, + hasClear: itemGroup.hasClear, + embeddedItems: itemGroup.isEmbedded ? itemGroup.items : nil, + constrainedSize: CGSize(width: itemLayout.contentSize.width - itemLayout.headerInsets.left - itemLayout.headerInsets.right, height: itemGroupLayout.headerHeight), + insets: itemLayout.headerInsets, + cache: component.animationCache, + renderer: component.animationRenderer, + attemptSynchronousLoad: attemptSynchronousLoads + ) + + if groupHeaderView.bounds.size != groupHeaderSize { + headerSizeUpdated = true + } + headerCentralContentWidth = centralContentWidth + + let groupHeaderFrame = CGRect(origin: CGPoint(x: floor((itemLayout.contentSize.width - groupHeaderSize.width) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + groupHeaderView.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size) + groupHeaderTransition.setPosition(view: groupHeaderView, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY)) + } + + let groupBorderRadius: CGFloat = 16.0 + + if itemGroup.isPremiumLocked && !itemGroup.isFeatured && !itemGroup.isEmbedded { + validGroupBorderIds.insert(itemGroup.groupId) + let groupBorderLayer: GroupBorderLayer + var groupBorderTransition = transition + if let current = self.visibleGroupBorders[itemGroup.groupId] { + groupBorderLayer = current + } else { + groupBorderTransition = .immediate + groupBorderLayer = GroupBorderLayer() + self.visibleGroupBorders[itemGroup.groupId] = groupBorderLayer + self.scrollView.layer.insertSublayer(groupBorderLayer, at: 0) + self.mirrorContentScrollView.layer.addSublayer(groupBorderLayer.tintContainerLayer) + + groupBorderLayer.strokeColor = keyboardChildEnvironment.theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor + groupBorderLayer.tintContainerLayer.strokeColor = UIColor.white.cgColor + groupBorderLayer.lineWidth = 1.6 + groupBorderLayer.lineCap = .round + groupBorderLayer.fillColor = nil + } + + let groupBorderHorizontalInset: CGFloat = itemLayout.itemInsets.left - 4.0 + let groupBorderVerticalTopOffset: CGFloat = 8.0 + let groupBorderVerticalInset: CGFloat = 6.0 + + let groupBorderFrame = CGRect(origin: CGPoint(x: groupBorderHorizontalInset, y: itemGroupLayout.frame.minY + groupBorderVerticalTopOffset), size: CGSize(width: itemLayout.width - groupBorderHorizontalInset * 2.0, height: itemGroupLayout.frame.size.height - groupBorderVerticalTopOffset + groupBorderVerticalInset)) + + if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated { + let headerWidth: CGFloat + if let headerCentralContentWidth = headerCentralContentWidth { + headerWidth = headerCentralContentWidth + 14.0 + } else { + headerWidth = 0.0 + } + let path = CGMutablePath() + let radius = groupBorderRadius + path.move(to: CGPoint(x: floor((groupBorderFrame.width - headerWidth) / 2.0), y: 0.0)) + path.addLine(to: CGPoint(x: radius, y: 0.0)) + path.addArc(tangent1End: CGPoint(x: 0.0, y: 0.0), tangent2End: CGPoint(x: 0.0, y: radius), radius: radius) + path.addLine(to: CGPoint(x: 0.0, y: groupBorderFrame.height - radius)) + path.addArc(tangent1End: CGPoint(x: 0.0, y: groupBorderFrame.height), tangent2End: CGPoint(x: radius, y: groupBorderFrame.height), radius: radius) + path.addLine(to: CGPoint(x: groupBorderFrame.width - radius, y: groupBorderFrame.height)) + path.addArc(tangent1End: CGPoint(x: groupBorderFrame.width, y: groupBorderFrame.height), tangent2End: CGPoint(x: groupBorderFrame.width, y: groupBorderFrame.height - radius), radius: radius) + path.addLine(to: CGPoint(x: groupBorderFrame.width, y: radius)) + path.addArc(tangent1End: CGPoint(x: groupBorderFrame.width, y: 0.0), tangent2End: CGPoint(x: groupBorderFrame.width - radius, y: 0.0), radius: radius) + path.addLine(to: CGPoint(x: floor((groupBorderFrame.width - headerWidth) / 2.0) + headerWidth, y: 0.0)) + + let pathLength = (2.0 * groupBorderFrame.width + 2.0 * groupBorderFrame.height - 8.0 * radius + 2.0 * .pi * radius) - headerWidth + + var numberOfDashes = Int(floor(pathLength / 6.0)) + if numberOfDashes % 2 == 0 { + numberOfDashes -= 1 + } + let wholeLength = 6.0 * CGFloat(numberOfDashes) + let remainingLength = pathLength - wholeLength + let dashSpace = remainingLength / CGFloat(numberOfDashes) + + groupBorderTransition.setShapeLayerPath(layer: groupBorderLayer, path: path) + groupBorderTransition.setShapeLayerLineDashPattern(layer: groupBorderLayer, pattern: [(5.0 + dashSpace) as NSNumber, (7.0 + dashSpace) as NSNumber]) + } + groupBorderTransition.setFrame(layer: groupBorderLayer, frame: groupBorderFrame) + } + + if (itemGroup.isPremiumLocked || itemGroup.isFeatured), !itemGroup.isEmbedded, case .compact = itemLayout.layoutType { + let groupPremiumButtonMeasuringFrame = CGRect(origin: CGPoint(x: itemLayout.itemInsets.left, y: itemGroupLayout.frame.maxY - 50.0 + 1.0), size: CGSize(width: 100.0, height: 50.0)) + + if effectiveVisibleBounds.intersects(groupPremiumButtonMeasuringFrame) { + validGroupPremiumButtonIds.insert(itemGroup.groupId) + + let groupPremiumButton: ComponentView + var groupPremiumButtonTransition = transition + if let current = self.visibleGroupPremiumButtons[itemGroup.groupId] { + groupPremiumButton = current + } else { + groupPremiumButtonTransition = .immediate + groupPremiumButton = ComponentView() + self.visibleGroupPremiumButtons[itemGroup.groupId] = groupPremiumButton + } + + let groupId = itemGroup.groupId + let isPremiumLocked = itemGroup.isPremiumLocked + + let title: String + let backgroundColor: UIColor + let backgroundColors: [UIColor] + let foregroundColor: UIColor + let animationName: String? + let gloss: Bool + if itemGroup.isPremiumLocked { + title = keyboardChildEnvironment.strings.EmojiInput_UnlockPack(itemGroup.title ?? "Emoji").string + backgroundColors = [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ] + backgroundColor = backgroundColors[0] + foregroundColor = .white + animationName = "premium_unlock" + gloss = true + } else { + title = keyboardChildEnvironment.strings.EmojiInput_AddPack(itemGroup.title ?? "Emoji").string + backgroundColors = [] + backgroundColor = keyboardChildEnvironment.theme.list.itemCheckColors.fillColor + foregroundColor = keyboardChildEnvironment.theme.list.itemCheckColors.foregroundColor + animationName = nil + gloss = false + } + + let groupPremiumButtonSize = groupPremiumButton.update( + transition: groupPremiumButtonTransition, + component: AnyComponent(SolidRoundedButtonComponent( + title: title, + theme: SolidRoundedButtonComponent.Theme( + backgroundColor: backgroundColor, + backgroundColors: backgroundColors, + foregroundColor: foregroundColor + ), + font: .bold, + fontSize: 17.0, + height: 50.0, + cornerRadius: groupBorderRadius, + gloss: gloss, + animationName: animationName, + iconPosition: .right, + iconSpacing: 4.0, + action: { [weak self] in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteractionHolder.inputInteraction?.addGroupAction(groupId, isPremiumLocked) + } + )), + environment: {}, + containerSize: CGSize(width: itemLayout.width - itemLayout.itemInsets.left - itemLayout.itemInsets.right, height: itemLayout.premiumButtonHeight) + ) + let groupPremiumButtonFrame = CGRect(origin: CGPoint(x: itemLayout.itemInsets.left, y: itemGroupLayout.frame.maxY - groupPremiumButtonSize.height + 1.0), size: groupPremiumButtonSize) + if let view = groupPremiumButton.view { + var animateIn = false + if view.superview == nil { + animateIn = true + self.scrollView.addSubview(view) + } + groupPremiumButtonTransition.setFrame(view: view, frame: groupPremiumButtonFrame) + if animateIn, !transition.animation.isImmediate { + view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + transition.animateScale(view: view, from: 0.01, to: 1.0) + } + } + } + } + + if !itemGroup.isEmbedded, let collapsedItemIndex = itemGroupLayout.collapsedItemIndex, let collapsedItemText = itemGroupLayout.collapsedItemText { + validGroupExpandActionButtons.insert(itemGroup.groupId) + let groupId = itemGroup.groupId + + var groupExpandActionButtonTransition = transition + let groupExpandActionButton: GroupExpandActionButton + if let current = self.visibleGroupExpandActionButtons[itemGroup.groupId] { + groupExpandActionButton = current + } else { + groupExpandActionButtonTransition = .immediate + groupExpandActionButton = GroupExpandActionButton(pressed: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.expandGroup(groupId: groupId) + }) + self.visibleGroupExpandActionButtons[itemGroup.groupId] = groupExpandActionButton + self.scrollView.addSubview(groupExpandActionButton) + self.mirrorContentScrollView.layer.addSublayer(groupExpandActionButton.tintContainerLayer) + } + + let baseItemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: collapsedItemIndex) + let buttonSize = groupExpandActionButton.update(theme: keyboardChildEnvironment.theme, title: collapsedItemText) + let buttonFrame = CGRect(origin: CGPoint(x: baseItemFrame.minX + floor((baseItemFrame.width - buttonSize.width) / 2.0), y: baseItemFrame.minY + floor((baseItemFrame.height - buttonSize.height) / 2.0)), size: buttonSize) + groupExpandActionButtonTransition.setFrame(view: groupExpandActionButton, frame: buttonFrame) + } + + if !itemGroup.isEmbedded, let groupItemRange = groupItems.groupItems { + for index in groupItemRange.lowerBound ..< groupItemRange.upperBound { + let item = itemGroup.items[index] + + if assignTopVisibleSubgroupId { + if let subgroupId = item.subgroupId { + topVisibleSubgroupId = AnyHashable(subgroupId) + } + } + + let itemId = ItemLayer.Key(groupId: itemGroup.groupId, fileId: item.file?.fileId, staticEmoji: item.staticEmoji) + validIds.insert(itemId) + + let itemDimensions: CGSize + if let file = item.file { + itemDimensions = file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0) + } else { + itemDimensions = CGSize(width: 512.0, height: 512.0) + } + let itemNativeFitSize = itemDimensions.aspectFitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) + let itemVisibleFitSize = itemDimensions.aspectFitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + let itemPlaybackSize = itemDimensions.aspectFitted(CGSize(width: itemLayout.playbackItemSize, height: itemLayout.playbackItemSize)) + + var animateItemIn = false + var updateItemLayerPlaceholder = false + var itemTransition = transition + let itemLayer: ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + updateItemLayerPlaceholder = true + itemTransition = .immediate + animateItemIn = !transition.animation.isImmediate + + let placeholderColor = keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1) + itemLayer = ItemLayer( + item: item, + context: component.context, + attemptSynchronousLoad: attemptSynchronousLoads, + file: item.file, + staticEmoji: item.staticEmoji, + cache: component.animationCache, + renderer: component.animationRenderer, + placeholderColor: placeholderColor, + blurredBadgeColor: keyboardChildEnvironment.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), + pointSize: item.staticEmoji == nil ? itemPlaybackSize : itemVisibleFitSize, + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in + guard let strongSelf = self else { + return + } + if displayPlaceholder, let file = item.file { + if let itemLayer = strongSelf.visibleItemLayers[itemId] { + let placeholderView: ItemPlaceholderView + if let current = strongSelf.visibleItemPlaceholderViews[itemId] { + placeholderView = current + } else { + placeholderView = ItemPlaceholderView( + context: component.context, + file: file, + shimmerView: strongSelf.shimmerHostView, + color: placeholderColor, + size: itemNativeFitSize + ) + strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView + strongSelf.placeholdersContainerView.addSubview(placeholderView) + } + placeholderView.frame = itemLayer.frame + placeholderView.update(size: placeholderView.bounds.size) + + strongSelf.updateShimmerIfNeeded() + } + } else { + if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { + strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) + + if duration > 0.0 { + placeholderView.layer.opacity = 0.0 + placeholderView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, completion: { [weak self, weak placeholderView] _ in + guard let strongSelf = self else { + return + } + placeholderView?.removeFromSuperview() + strongSelf.updateShimmerIfNeeded() + }) + } else { + placeholderView.removeFromSuperview() + strongSelf.updateShimmerIfNeeded() + } + } + } + } + ) + self.scrollView.layer.addSublayer(itemLayer) + self.visibleItemLayers[itemId] = itemLayer + } + + var itemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index) + + itemFrame.origin.x += floor((itemFrame.width - itemVisibleFitSize.width) / 2.0) + itemFrame.origin.y += floor((itemFrame.height - itemVisibleFitSize.height) / 2.0) + itemFrame.size = itemVisibleFitSize + + let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) + itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + if animateItemIn, !transition.animation.isImmediate { + if let previousItemPosition = previousItemPositions?[itemId], transitionHintInstalledGroupId != itemId.groupId, transitionHintExpandedGroupId != itemId.groupId { + itemTransition = transition + itemLayer.position = previousItemPosition + } else { + if let contentAnimation = contentAnimation, case .groupExpanded(id: itemGroup.groupId) = contentAnimation.type { + itemLayer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) + itemLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } else { + itemLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } + } + + let itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + itemTransition.setPosition(layer: itemLayer, position: itemPosition) + + var badge: ItemLayer.Badge? + if itemGroup.displayPremiumBadges, let file = item.file, file.isPremiumSticker { + badge = .premium + } + itemLayer.update(transition: transition, size: itemFrame.size, badge: badge, blurredBadgeColor: UIColor(white: 0.0, alpha: 0.1), blurredBadgeBackgroundColor: keyboardChildEnvironment.theme.list.plainBackgroundColor) + + if let placeholderView = self.visibleItemPlaceholderViews[itemId] { + if placeholderView.layer.position != itemPosition || placeholderView.layer.bounds != itemBounds { + itemTransition.setFrame(view: placeholderView, frame: itemFrame) + placeholderView.update(size: itemFrame.size) + } + } else if updateItemLayerPlaceholder { + if itemLayer.displayPlaceholder { + itemLayer.onUpdateDisplayPlaceholder(true, 0.0) + } + } + + if animateItemIn, !transition.animation.isImmediate, let contentAnimation = contentAnimation, case .groupExpanded(id: itemGroup.groupId) = contentAnimation.type, let placeholderView = self.visibleItemPlaceholderViews[itemId] { + placeholderView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) + placeholderView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + } + + itemLayer.isVisibleForAnimations = true + } + } + } + + var removedPlaceholerViews = false + var removedIds: [ItemLayer.Key] = [] + for (id, itemLayer) in self.visibleItemLayers { + if !validIds.contains(id) { + removedIds.append(id) + + if !transition.animation.isImmediate { + if let position = updatedItemPositions?[id], transitionHintInstalledGroupId != id.groupId { + transition.setPosition(layer: itemLayer, position: position, completion: { [weak itemLayer] _ in + itemLayer?.removeFromSuperlayer() + }) + } else { + itemLayer.opacity = 0.0 + itemLayer.animateScale(from: 1.0, to: 0.01, duration: 0.2) + itemLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak itemLayer] _ in + itemLayer?.removeFromSuperlayer() + }) + } + } else { + itemLayer.removeFromSuperlayer() + } + } + } + for id in removedIds { + self.visibleItemLayers.removeValue(forKey: id) + + if let view = self.visibleItemPlaceholderViews.removeValue(forKey: id) { + view.removeFromSuperview() + removedPlaceholerViews = true + } + } + + var removedGroupHeaderIds: [AnyHashable] = [] + for (id, groupHeaderLayer) in self.visibleGroupHeaders { + if !validGroupHeaderIds.contains(id) { + removedGroupHeaderIds.append(id) + + if !transition.animation.isImmediate { + groupHeaderLayer.alpha = 0.0 + groupHeaderLayer.layer.animateScale(from: 1.0, to: 0.5, duration: 0.2) + let tintContentLayer = groupHeaderLayer.tintContentLayer + groupHeaderLayer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak groupHeaderLayer, weak tintContentLayer] _ in + groupHeaderLayer?.removeFromSuperview() + tintContentLayer?.removeFromSuperlayer() + }) + } else { + groupHeaderLayer.removeFromSuperview() + groupHeaderLayer.tintContentLayer.removeFromSuperlayer() + } + } + } + for id in removedGroupHeaderIds { + self.visibleGroupHeaders.removeValue(forKey: id) + } + + var removedGroupBorderIds: [AnyHashable] = [] + for (id, groupBorderLayer) in self.visibleGroupBorders { + if !validGroupBorderIds.contains(id) { + removedGroupBorderIds.append(id) + groupBorderLayer.removeFromSuperlayer() + groupBorderLayer.tintContainerLayer.removeFromSuperlayer() + } + } + for id in removedGroupBorderIds { + self.visibleGroupBorders.removeValue(forKey: id) + } + + var removedGroupPremiumButtonIds: [AnyHashable] = [] + for (id, groupPremiumButton) in self.visibleGroupPremiumButtons { + if !validGroupPremiumButtonIds.contains(id) { + removedGroupPremiumButtonIds.append(id) + groupPremiumButton.view?.removeFromSuperview() + } + } + for id in removedGroupPremiumButtonIds { + self.visibleGroupPremiumButtons.removeValue(forKey: id) + } + + var removedGroupExpandActionButtonIds: [AnyHashable] = [] + for (id, button) in self.visibleGroupExpandActionButtons { + if !validGroupExpandActionButtons.contains(id) { + removedGroupExpandActionButtonIds.append(id) + + if !transition.animation.isImmediate && transitionHintExpandedGroupId == id { + button.alpha = 0.0 + button.layer.animateScale(from: 1.0, to: 0.5, duration: 0.2) + let tintContainerLayer = button.tintContainerLayer + button.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak button, weak tintContainerLayer] _ in + button?.removeFromSuperview() + tintContainerLayer?.removeFromSuperlayer() + }) + } else { + button.removeFromSuperview() + button.tintContainerLayer.removeFromSuperlayer() + } + } + } + for id in removedGroupExpandActionButtonIds { + self.visibleGroupExpandActionButtons.removeValue(forKey: id) + } + + if removedPlaceholerViews { + self.updateShimmerIfNeeded() + } + + if let topVisibleGroupId = topVisibleGroupId { + self.activeItemUpdated?.invoke((topVisibleGroupId, topVisibleSubgroupId, .immediate)) + } + } + + private func updateShimmerIfNeeded() { + if let standaloneShimmerEffect = self.standaloneShimmerEffect, let shimmerHostView = self.shimmerHostView { + if self.placeholdersContainerView.subviews.isEmpty { + standaloneShimmerEffect.layer = nil + } else { + standaloneShimmerEffect.layer = shimmerHostView.layer + } + } + } + + private func expandGroup(groupId: AnyHashable) { + self.expandedGroupIds.insert(groupId) + + self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(ContentAnimation(type: .groupExpanded(id: groupId)))) + } + + public func pagerUpdateBackground(backgroundFrame: CGRect, transition: Transition) { + guard let keyboardChildEnvironment = self.keyboardChildEnvironment else { + return + } + + if self.vibrancyEffectView == nil { + let style: UIBlurEffect.Style + style = .extraLight + let blurEffect = UIBlurEffect(style: style) + let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) + let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect) + self.vibrancyEffectView = vibrancyEffectView + self.backgroundView.addSubview(vibrancyEffectView) + for subview in vibrancyEffectView.subviews { + let _ = subview + } + vibrancyEffectView.contentView.addSubview(self.mirrorContentScrollView) + } + + self.backgroundView.updateColor(color: keyboardChildEnvironment.theme.chat.inputMediaPanel.backgroundColor, enableBlur: true, forceKeepBlur: false, transition: transition.containedViewLayoutTransition) + transition.setFrame(view: self.backgroundView, frame: backgroundFrame) + self.backgroundView.update(size: backgroundFrame.size, transition: transition.containedViewLayoutTransition) + + if let vibrancyEffectView = self.vibrancyEffectView { + transition.setFrame(view: vibrancyEffectView, frame: CGRect(origin: CGPoint(x: 0.0, y: -backgroundFrame.minY), size: CGSize(width: backgroundFrame.width, height: backgroundFrame.height + backgroundFrame.minY))) + } + } + + func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let previousComponent = self.component + + self.component = component + self.state = state + + self.peekRecognizer?.isEnabled = component.itemLayoutType == .detailed + + let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value + let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value + + self.keyboardChildEnvironment = keyboardChildEnvironment + self.activeItemUpdated = keyboardChildEnvironment.getContentActiveItemUpdated(component.id) + + self.pagerEnvironment = pagerEnvironment + + if let shimmerHostView = self.shimmerHostView { + transition.setFrame(view: shimmerHostView, frame: CGRect(origin: CGPoint(), size: availableSize)) + } + + if let standaloneShimmerEffect = self.standaloneShimmerEffect { + let shimmerBackgroundColor = keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08) + let shimmerForegroundColor = keyboardChildEnvironment.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) + standaloneShimmerEffect.update(background: shimmerBackgroundColor, foreground: shimmerForegroundColor) + } + + var previousItemPositions: [ItemLayer.Key: CGPoint]? + + var calculateUpdatedItemPositions = false + var updatedItemPositions: [ItemLayer.Key: CGPoint]? + + var anchorItem: (key: ItemLayer.Key, frame: CGRect)? + if let previousComponent = previousComponent, let previousItemLayout = self.itemLayout, previousComponent.itemGroups != component.itemGroups { + if !transition.animation.isImmediate { + var previousItemPositionsValue: [ItemLayer.Key: CGPoint] = [:] + for groupIndex in 0 ..< previousComponent.itemGroups.count { + let itemGroup = previousComponent.itemGroups[groupIndex] + for itemIndex in 0 ..< itemGroup.items.count { + let item = itemGroup.items[itemIndex] + let itemKey: ItemLayer.Key + if let file = item.file { + itemKey = ItemLayer.Key(groupId: itemGroup.groupId, fileId: file.fileId, staticEmoji: nil) + } else if let staticEmoji = item.staticEmoji { + itemKey = ItemLayer.Key(groupId: itemGroup.groupId, fileId: nil, staticEmoji: staticEmoji) + } else { + continue + } + let itemFrame = previousItemLayout.frame(groupIndex: groupIndex, itemIndex: itemIndex) + previousItemPositionsValue[itemKey] = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + } + } + previousItemPositions = previousItemPositionsValue + calculateUpdatedItemPositions = true + } + + let effectiveVisibleBounds = CGRect(origin: self.scrollView.bounds.origin, size: self.effectiveVisibleSize) + let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: pagerEnvironment.containerInsets.top) + for (key, itemLayer) in self.visibleItemLayers { + if !topVisibleDetectionBounds.intersects(itemLayer.frame) { + continue + } + if let anchorItemValue = anchorItem { + if itemLayer.frame.minY < anchorItemValue.frame.minY { + anchorItem = (key, itemLayer.frame) + } else if itemLayer.frame.minY == anchorItemValue.frame.minY && itemLayer.frame.minX < anchorItemValue.frame.minX { + anchorItem = (key, itemLayer.frame) + } + } else { + anchorItem = (key, itemLayer.frame) + } + } + if let anchorItemValue = anchorItem { + anchorItem = (anchorItemValue.key, self.scrollView.convert(anchorItemValue.frame, to: self)) + } + } + + var itemGroups: [ItemGroupDescription] = [] + for itemGroup in component.itemGroups { + itemGroups.append(ItemGroupDescription( + supergroupId: itemGroup.supergroupId, + groupId: itemGroup.groupId, + hasTitle: itemGroup.title != nil, + isPremiumLocked: itemGroup.isPremiumLocked, + isFeatured: itemGroup.isFeatured, + itemCount: itemGroup.items.count, + isEmbedded: itemGroup.isEmbedded, + isExpandable: itemGroup.isExpandable + )) + } + + var itemTransition = transition + + let itemLayout = ItemLayout( + layoutType: component.itemLayoutType, + width: availableSize.width, + containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right), + itemGroups: itemGroups, + expandedGroupIds: self.expandedGroupIds + ) + if let previousItemLayout = self.itemLayout { + if previousItemLayout.width != itemLayout.width { + itemTransition = .immediate + } else if transition.userData(ContentAnimation.self) == nil { + itemTransition = .immediate + } + } else { + itemTransition = .immediate + } + self.itemLayout = itemLayout + + self.ignoreScrolling = true + transition.setPosition(view: self.scrollView, position: CGPoint()) + let previousSize = self.scrollView.bounds.size + self.scrollView.bounds = CGRect(origin: self.scrollView.bounds.origin, size: availableSize) + + if availableSize.height > previousSize.height || transition.animation.isImmediate { + self.boundsChangeTrackerLayer.removeAllAnimations() + self.boundsChangeTrackerLayer.bounds = self.scrollView.bounds + self.effectiveVisibleSize = self.scrollView.bounds.size + } else { + self.effectiveVisibleSize = CGSize(width: availableSize.width, height: max(self.effectiveVisibleSize.height, availableSize.height)) + transition.setBounds(layer: self.boundsChangeTrackerLayer, bounds: self.scrollView.bounds, completion: { [weak self] completed in + guard let strongSelf = self else { + return + } + let effectiveVisibleSize = strongSelf.scrollView.bounds.size + if strongSelf.effectiveVisibleSize != effectiveVisibleSize { + strongSelf.effectiveVisibleSize = effectiveVisibleSize + strongSelf.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false, previousItemPositions: nil, updatedItemPositions: nil) + } + }) + } + + if self.scrollView.contentSize != itemLayout.contentSize { + self.scrollView.contentSize = itemLayout.contentSize + } + if self.scrollView.scrollIndicatorInsets != pagerEnvironment.containerInsets { + self.scrollView.scrollIndicatorInsets = pagerEnvironment.containerInsets + } + self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: scrollView.isDragging || scrollView.isDecelerating) + + if let anchorItem = anchorItem { + outer: for i in 0 ..< component.itemGroups.count { + if component.itemGroups[i].groupId != anchorItem.key.groupId { + continue + } + for j in 0 ..< component.itemGroups[i].items.count { + let itemKey: ItemLayer.Key + if let file = component.itemGroups[i].items[j].file { + itemKey = ItemLayer.Key(groupId: component.itemGroups[i].groupId, fileId: file.fileId, staticEmoji: nil) + } else if let staticEmoji = component.itemGroups[i].items[j].staticEmoji { + itemKey = ItemLayer.Key(groupId: component.itemGroups[i].groupId, fileId: nil, staticEmoji: staticEmoji) + } else { + continue + } + + if itemKey == anchorItem.key { + let itemFrame = itemLayout.frame(groupIndex: i, itemIndex: j) + + var contentOffsetY = itemFrame.minY - anchorItem.frame.minY + if contentOffsetY > self.scrollView.contentSize.height - self.scrollView.bounds.height { + contentOffsetY = self.scrollView.contentSize.height - self.scrollView.bounds.height + } + if contentOffsetY < 0.0 { + contentOffsetY = 0.0 + } + + let previousBounds = self.scrollView.bounds + self.scrollView.setContentOffset(CGPoint(x: 0.0, y: contentOffsetY), animated: false) + transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: previousBounds.minY - contentOffsetY), to: CGPoint(), additive: true) + + break outer + } + } + } + } + + self.ignoreScrolling = false + + if calculateUpdatedItemPositions { + var updatedItemPositionsValue: [ItemLayer.Key: CGPoint] = [:] + for groupIndex in 0 ..< component.itemGroups.count { + let itemGroup = component.itemGroups[groupIndex] + for itemIndex in 0 ..< itemGroup.items.count { + let item = itemGroup.items[itemIndex] + let itemKey: ItemLayer.Key + if let file = item.file { + itemKey = ItemLayer.Key(groupId: itemGroup.groupId, fileId: file.fileId, staticEmoji: nil) + } else if let staticEmoji = item.staticEmoji { + itemKey = ItemLayer.Key(groupId: itemGroup.groupId, fileId: nil, staticEmoji: staticEmoji) + } else { + continue + } + let itemFrame = itemLayout.frame(groupIndex: groupIndex, itemIndex: itemIndex) + updatedItemPositionsValue[itemKey] = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + } + } + updatedItemPositions = updatedItemPositionsValue + } + + self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating), previousItemPositions: previousItemPositions, updatedItemPositions: updatedItemPositions) + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift new file mode 100644 index 0000000000..b3423d2bbc --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -0,0 +1,766 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import BlurredBackgroundComponent +import BundleIconComponent +import AudioToolbox +import SwiftSignalKit + +public final class EntityKeyboardChildEnvironment: Equatable { + public let theme: PresentationTheme + public let strings: PresentationStrings + public let getContentActiveItemUpdated: (AnyHashable) -> ActionSlot<(AnyHashable, AnyHashable?, Transition)>? + + public init( + theme: PresentationTheme, + strings: PresentationStrings, + getContentActiveItemUpdated: @escaping (AnyHashable) -> ActionSlot<(AnyHashable, AnyHashable?, Transition)>? + ) { + self.theme = theme + self.strings = strings + self.getContentActiveItemUpdated = getContentActiveItemUpdated + } + + public static func ==(lhs: EntityKeyboardChildEnvironment, rhs: EntityKeyboardChildEnvironment) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + + return true + } +} + +public enum EntitySearchContentType { + case stickers + case gifs +} + +public final class EntityKeyboardComponent: Component { + public final class MarkInputCollapsed { + public init() { + } + } + + private enum ReorderCategory { + case stickers + case emoji + } + + public struct GifSearchEmoji: Equatable { + public var emoji: String + public var file: TelegramMediaFile + public var title: String + + public init(emoji: String, file: TelegramMediaFile, title: String) { + self.emoji = emoji + self.file = file + self.title = title + } + + public static func ==(lhs: GifSearchEmoji, rhs: GifSearchEmoji) -> Bool { + if lhs.emoji != rhs.emoji { + return false + } + if lhs.file.fileId != rhs.file.fileId { + return false + } + if lhs.title != rhs.title { + return false + } + return true + } + } + + public let theme: PresentationTheme + public let strings: PresentationStrings + public let containerInsets: UIEdgeInsets + public let emojiContent: EmojiPagerContentComponent + public let stickerContent: EmojiPagerContentComponent? + public let gifContent: GifPagerContentComponent? + public let hasRecentGifs: Bool + public let availableGifSearchEmojies: [GifSearchEmoji] + public let defaultToEmojiTab: Bool + public let externalTopPanelContainer: PagerExternalTopPanelContainer? + public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void + public let hideInputUpdated: (Bool, Bool, Transition) -> Void + public let switchToTextInput: () -> Void + public let switchToGifSubject: (GifPagerContentComponent.Subject) -> Void + public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode? + public let deviceMetrics: DeviceMetrics + public let hiddenInputHeight: CGFloat + public let isExpanded: Bool + + public init( + theme: PresentationTheme, + strings: PresentationStrings, + containerInsets: UIEdgeInsets, + emojiContent: EmojiPagerContentComponent, + stickerContent: EmojiPagerContentComponent?, + gifContent: GifPagerContentComponent?, + hasRecentGifs: Bool, + availableGifSearchEmojies: [GifSearchEmoji], + defaultToEmojiTab: Bool, + externalTopPanelContainer: PagerExternalTopPanelContainer?, + topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void, + hideInputUpdated: @escaping (Bool, Bool, Transition) -> Void, + switchToTextInput: @escaping () -> Void, + switchToGifSubject: @escaping (GifPagerContentComponent.Subject) -> Void, + makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode?, + deviceMetrics: DeviceMetrics, + hiddenInputHeight: CGFloat, + isExpanded: Bool + ) { + self.theme = theme + self.strings = strings + self.containerInsets = containerInsets + self.emojiContent = emojiContent + self.stickerContent = stickerContent + self.gifContent = gifContent + self.hasRecentGifs = hasRecentGifs + self.availableGifSearchEmojies = availableGifSearchEmojies + self.defaultToEmojiTab = defaultToEmojiTab + self.externalTopPanelContainer = externalTopPanelContainer + self.topPanelExtensionUpdated = topPanelExtensionUpdated + self.hideInputUpdated = hideInputUpdated + self.switchToTextInput = switchToTextInput + self.switchToGifSubject = switchToGifSubject + self.makeSearchContainerNode = makeSearchContainerNode + self.deviceMetrics = deviceMetrics + self.hiddenInputHeight = hiddenInputHeight + self.isExpanded = isExpanded + } + + public static func ==(lhs: EntityKeyboardComponent, rhs: EntityKeyboardComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + if lhs.containerInsets != rhs.containerInsets { + return false + } + if lhs.emojiContent != rhs.emojiContent { + return false + } + if lhs.stickerContent != rhs.stickerContent { + return false + } + if lhs.gifContent != rhs.gifContent { + return false + } + if lhs.hasRecentGifs != rhs.hasRecentGifs { + return false + } + if lhs.availableGifSearchEmojies != rhs.availableGifSearchEmojies { + return false + } + if lhs.defaultToEmojiTab != rhs.defaultToEmojiTab { + return false + } + if lhs.externalTopPanelContainer != rhs.externalTopPanelContainer { + return false + } + if lhs.deviceMetrics != rhs.deviceMetrics { + return false + } + if lhs.hiddenInputHeight != rhs.hiddenInputHeight { + return false + } + if lhs.isExpanded != rhs.isExpanded { + return false + } + + return true + } + + public final class View: UIView { + private let tintContainerView: UIView + + private let pagerView: ComponentHostView + + private var component: EntityKeyboardComponent? + private weak var state: EmptyComponentState? + + private var searchView: ComponentHostView? + private var searchComponent: EntitySearchContentComponent? + + private var topPanelExtension: CGFloat? + private var isTopPanelExpanded: Bool = false + + public var centralId: AnyHashable? { + if let pagerView = self.pagerView.findTaggedView(tag: PagerComponentViewTag()) as? PagerComponent.View { + return pagerView.centralId + } else { + return nil + } + } + + override init(frame: CGRect) { + self.tintContainerView = UIView() + self.pagerView = ComponentHostView() + + super.init(frame: frame) + + //self.clipsToBounds = true + self.disablesInteractiveTransitionGestureRecognizer = true + + self.addSubview(self.pagerView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: EntityKeyboardComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.state = state + + var contents: [AnyComponentWithIdentity<(EntityKeyboardChildEnvironment, PagerComponentChildEnvironment)>] = [] + var contentTopPanels: [AnyComponentWithIdentity] = [] + var contentIcons: [PagerComponentContentIcon] = [] + var contentAccessoryLeftButtons: [AnyComponentWithIdentity] = [] + var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] + + let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, AnyHashable?, Transition)>() + let stickersContentItemIdUpdated = ActionSlot<(AnyHashable, AnyHashable?, Transition)>() + + if transition.userData(MarkInputCollapsed.self) != nil { + self.searchComponent = nil + } + + if let gifContent = component.gifContent { + contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(gifContent))) + var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] + if component.hasRecentGifs { + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "recent", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: .recent, + theme: component.theme, + title: component.strings.Stickers_Recent, + pressed: { [weak self] in + self?.component?.switchToGifSubject(.recent) + } + )) + )) + } + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "trending", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: .trending, + theme: component.theme, + title: component.strings.Stickers_Trending, + pressed: { [weak self] in + self?.component?.switchToGifSubject(.trending) + } + )) + )) + for emoji in component.availableGifSearchEmojies { + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: emoji.emoji, + isReorderable: false, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.emojiContent.context, + file: emoji.file, + isFeatured: false, + isPremiumLocked: false, + animationCache: component.emojiContent.animationCache, + animationRenderer: component.emojiContent.animationRenderer, + theme: component.theme, + title: emoji.title, + pressed: { [weak self] in + self?.component?.switchToGifSubject(.emojiSearch(emoji.emoji)) + } + )) + )) + } + let defaultActiveGifItemId: AnyHashable + switch gifContent.subject { + case .recent: + defaultActiveGifItemId = "recent" + case .trending: + defaultActiveGifItemId = "trending" + case let .emojiSearch(value): + defaultActiveGifItemId = AnyHashable(value) + } + contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topGifItems, + containerSideInset: component.containerInsets.left, + forceActiveItemId: defaultActiveGifItemId, + activeContentItemIdUpdated: gifsContentItemIdUpdated, + reorderItems: { _ in + } + )))) + contentIcons.append(PagerComponentContentIcon(id: "gifs", imageName: "Chat/Input/Media/EntityInputGifsIcon")) + contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputSearchIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { [weak self] in + self?.openSearch() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + } + + if let stickerContent = component.stickerContent { + var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] + + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: "featuredTop", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: .featured, + theme: component.theme, + title: component.strings.Stickers_Trending, + pressed: { [weak self] in + self?.component?.stickerContent?.inputInteractionHolder.inputInteraction?.openFeatured() + } + )) + )) + + for itemGroup in stickerContent.itemGroups { + if let id = itemGroup.supergroupId.base as? String { + let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [ + "saved": .saved, + "recent": .recent, + "premium": .premium + ] + let titleMapping: [String: String] = [ + "saved": component.strings.Stickers_Favorites, + "recent": component.strings.Stickers_Recent, + "premium": component.strings.EmojiInput_PanelTitlePremium + ] + if let icon = iconMapping[id], let title = titleMapping[id] { + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: icon, + theme: component.theme, + title: title, + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) + )) + } + } else { + if !itemGroup.items.isEmpty { + if let file = itemGroup.items[0].file { + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: !itemGroup.isFeatured, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: stickerContent.context, + file: file, + isFeatured: itemGroup.isFeatured, + isPremiumLocked: itemGroup.isPremiumLocked, + animationCache: stickerContent.animationCache, + animationRenderer: stickerContent.animationRenderer, + theme: component.theme, + title: itemGroup.title ?? "", + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) + )) + } + } + } + } + contents.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(stickerContent))) + contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topStickerItems, + containerSideInset: component.containerInsets.left, + defaultActiveItemId: stickerContent.itemGroups.first?.groupId, + activeContentItemIdUpdated: stickersContentItemIdUpdated, + reorderItems: { [weak self] items in + guard let strongSelf = self else { + return + } + strongSelf.reorderPacks(category: .stickers, items: items) + } + )))) + contentIcons.append(PagerComponentContentIcon(id: "stickers", imageName: "Chat/Input/Media/EntityInputStickersIcon")) + contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputSearchIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { [weak self] in + self?.openSearch() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputSettingsIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { + stickerContent.inputInteractionHolder.inputInteraction?.openStickerSettings() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + } + + let emojiContentItemIdUpdated = ActionSlot<(AnyHashable, AnyHashable?, Transition)>() + contents.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(component.emojiContent))) + var topEmojiItems: [EntityKeyboardTopPanelComponent.Item] = [] + for itemGroup in component.emojiContent.itemGroups { + if !itemGroup.items.isEmpty { + if let id = itemGroup.groupId.base as? String { + if id == "recent" { + let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [ + "recent": .recent, + ] + let titleMapping: [String: String] = [ + "recent": component.strings.Stickers_Recent, + ] + if let icon = iconMapping[id], let title = titleMapping[id] { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: icon, + theme: component.theme, + title: title, + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) + )) + } + } else if id == "static" { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: false, + content: AnyComponent(EntityKeyboardStaticStickersPanelComponent( + theme: component.theme, + title: component.strings.EmojiInput_PanelTitleEmoji, + pressed: { [weak self] subgroupId in + guard let strongSelf = self else { + return + } + strongSelf.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.supergroupId, subgroupId: subgroupId.rawValue) + } + )) + )) + } + } else { + if let file = itemGroup.items[0].file { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: !itemGroup.isFeatured, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.emojiContent.context, + file: file, + isFeatured: itemGroup.isFeatured, + isPremiumLocked: itemGroup.isPremiumLocked, + animationCache: component.emojiContent.animationCache, + animationRenderer: component.emojiContent.animationRenderer, + theme: component.theme, + title: itemGroup.title ?? "", + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) + )) + } + } + } + } + contentTopPanels.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topEmojiItems, + containerSideInset: component.containerInsets.left, + activeContentItemIdUpdated: emojiContentItemIdUpdated, + reorderItems: { [weak self] items in + guard let strongSelf = self else { + return + } + strongSelf.reorderPacks(category: .emoji, items: items) + } + )))) + contentIcons.append(PagerComponentContentIcon(id: "emoji", imageName: "Chat/Input/Media/EntityInputEmojiIcon")) + contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputGlobeIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { [weak self] in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.switchToTextInput() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + let deleteBackwards = component.emojiContent.inputInteractionHolder.inputInteraction?.deleteBackwards + contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputClearIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { + deleteBackwards?() + AudioServicesPlaySystemSound(1155) + } + ).withHoldAction({ + deleteBackwards?() + AudioServicesPlaySystemSound(1155) + }).minSize(CGSize(width: 38.0, height: 38.0))))) + + let panelHideBehavior: PagerComponentPanelHideBehavior + if self.searchComponent != nil { + panelHideBehavior = .hide + } else if component.isExpanded { + panelHideBehavior = .show + } else { + panelHideBehavior = .hideOnScroll + } + + let pagerSize = self.pagerView.update( + transition: transition, + component: AnyComponent(PagerComponent( + contentInsets: component.containerInsets, + contents: contents, + contentTopPanels: contentTopPanels, + contentIcons: contentIcons, + contentAccessoryLeftButtons: contentAccessoryLeftButtons, + contentAccessoryRightButtons: contentAccessoryRightButtons, + defaultId: component.defaultToEmojiTab ? "emoji" : "stickers", + contentBackground: nil, + topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( + theme: component.theme, + overflowHeight: component.hiddenInputHeight, + displayBackground: component.externalTopPanelContainer == nil + )), + externalTopPanelContainer: component.externalTopPanelContainer, + bottomPanel: AnyComponent(EntityKeyboardBottomPanelComponent( + theme: component.theme, + containerInsets: component.containerInsets, + deleteBackwards: { [weak self] in + self?.component?.emojiContent.inputInteractionHolder.inputInteraction?.deleteBackwards() + AudioServicesPlaySystemSound(0x451) + } + )), + panelStateUpdated: { [weak self] panelState, transition in + guard let strongSelf = self else { + return + } + strongSelf.topPanelExtensionUpdated(height: panelState.topPanelHeight, transition: transition) + }, + isTopPanelExpandedUpdated: { [weak self] isExpanded, transition in + guard let strongSelf = self else { + return + } + strongSelf.isTopPanelExpandedUpdated(isExpanded: isExpanded, transition: transition) + }, + panelHideBehavior: panelHideBehavior + )), + environment: { + EntityKeyboardChildEnvironment( + theme: component.theme, + strings: component.strings, + getContentActiveItemUpdated: { id in + if id == AnyHashable("gifs") { + return gifsContentItemIdUpdated + } else if id == AnyHashable("stickers") { + return stickersContentItemIdUpdated + } else if id == AnyHashable("emoji") { + return emojiContentItemIdUpdated + } + return nil + } + ) + }, + containerSize: availableSize + ) + transition.setFrame(view: self.pagerView, frame: CGRect(origin: CGPoint(), size: pagerSize)) + + if let searchComponent = self.searchComponent { + var animateIn = false + let searchView: ComponentHostView + var searchViewTransition = transition + if let current = self.searchView { + searchView = current + } else { + searchViewTransition = .immediate + searchView = ComponentHostView() + self.searchView = searchView + self.addSubview(searchView) + + animateIn = true + component.topPanelExtensionUpdated(0.0, transition) + } + + let _ = searchView.update( + transition: searchViewTransition, + component: AnyComponent(searchComponent), + environment: { + EntitySearchContentEnvironment( + context: component.emojiContent.context, + theme: component.theme, + deviceMetrics: component.deviceMetrics + ) + }, + containerSize: availableSize + ) + searchViewTransition.setFrame(view: searchView, frame: CGRect(origin: CGPoint(), size: availableSize)) + + if animateIn { + transition.animateAlpha(view: searchView, from: 0.0, to: 1.0) + transition.animatePosition(view: searchView, from: CGPoint(x: 0.0, y: self.topPanelExtension ?? 0.0), to: CGPoint(), additive: true, completion: nil) + } + } else { + if let searchView = self.searchView { + self.searchView = nil + + transition.setFrame(view: searchView, frame: CGRect(origin: CGPoint(x: 0.0, y: self.topPanelExtension ?? 0.0), size: availableSize)) + transition.setAlpha(view: searchView, alpha: 0.0, completion: { [weak searchView] _ in + searchView?.removeFromSuperview() + }) + + if let topPanelExtension = self.topPanelExtension { + component.topPanelExtensionUpdated(topPanelExtension, transition) + } + } + } + + self.component = component + + return availableSize + } + + private func topPanelExtensionUpdated(height: CGFloat, transition: Transition) { + guard let component = self.component else { + return + } + if self.topPanelExtension != height { + self.topPanelExtension = height + } + if self.searchComponent == nil { + component.topPanelExtensionUpdated(height, transition) + } + } + + private func isTopPanelExpandedUpdated(isExpanded: Bool, transition: Transition) { + if self.isTopPanelExpanded != isExpanded { + self.isTopPanelExpanded = isExpanded + } + + guard let component = self.component else { + return + } + + component.hideInputUpdated(self.isTopPanelExpanded, false, transition) + } + + private func openSearch() { + guard let component = self.component else { + return + } + if self.searchComponent != nil { + return + } + + if let pagerView = self.pagerView.findTaggedView(tag: PagerComponentViewTag()) as? PagerComponent.View, let centralId = pagerView.centralId { + let contentType: EntitySearchContentType + if centralId == AnyHashable("gifs") { + contentType = .gifs + } else { + contentType = .stickers + } + + self.searchComponent = EntitySearchContentComponent( + makeContainerNode: { + return component.makeSearchContainerNode(contentType) + }, + dismissSearch: { [weak self] in + self?.closeSearch() + } + ) + //self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) + component.hideInputUpdated(true, true, Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + } + + private func closeSearch() { + guard let component = self.component else { + return + } + if self.searchComponent == nil { + return + } + self.searchComponent = nil + //self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + component.hideInputUpdated(false, false, Transition(animation: .curve(duration: 0.4, curve: .spring))) + } + + private func scrollToItemGroup(contentId: String, groupId: AnyHashable, subgroupId: Int32?) { + guard let pagerView = self.pagerView.findTaggedView(tag: PagerComponentViewTag()) as? PagerComponent.View else { + return + } + guard let pagerContentView = self.pagerView.findTaggedView(tag: EmojiPagerContentComponent.Tag(id: contentId)) as? EmojiPagerContentComponent.View else { + return + } + if let topPanelView = pagerView.topPanelComponentView as? EntityKeyboardTopContainerPanelComponent.View { + topPanelView.internalUpdatePanelsAreCollapsed() + } + pagerContentView.scrollToItemGroup(id: groupId, subgroupId: subgroupId) + pagerView.collapseTopPanel() + } + + private func reorderPacks(category: ReorderCategory, items: [EntityKeyboardTopPanelComponent.Item]) { + guard let component = self.component else { + return + } + + var currentIds: [ItemCollectionId] = [] + for item in items { + guard let id = item.id.base as? ItemCollectionId else { + continue + } + currentIds.append(id) + } + let namespace: ItemCollectionId.Namespace + switch category { + case .stickers: + namespace = Namespaces.ItemCollection.CloudStickerPacks + case .emoji: + namespace = Namespaces.ItemCollection.CloudEmojiPacks + } + let _ = (component.emojiContent.context.engine.stickers.reorderStickerPacks(namespace: namespace, itemIds: currentIds) + |> deliverOnMainQueue).start(completed: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + }) + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift new file mode 100644 index 0000000000..5cc31d874b --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -0,0 +1,407 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import ComponentDisplayAdapters +import BundleIconComponent + +private final class BottomPanelIconComponent: Component { + let imageName: String + let isHighlighted: Bool + let theme: PresentationTheme + let action: () -> Void + + init( + imageName: String, + isHighlighted: Bool, + theme: PresentationTheme, + action: @escaping () -> Void + ) { + self.imageName = imageName + self.isHighlighted = isHighlighted + self.theme = theme + self.action = action + } + + static func ==(lhs: BottomPanelIconComponent, rhs: BottomPanelIconComponent) -> Bool { + if lhs.imageName != rhs.imageName { + return false + } + if lhs.isHighlighted != rhs.isHighlighted { + return false + } + if lhs.theme !== rhs.theme { + return false + } + + return true + } + + final class View: UIView { + let contentView: UIImageView + + var component: BottomPanelIconComponent? + + override init(frame: CGRect) { + self.contentView = UIImageView() + self.contentView.isUserInteractionEnabled = false + + super.init(frame: frame) + + self.addSubview(self.contentView) + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.component?.action() + } + } + + func update(component: BottomPanelIconComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + if self.component?.imageName != component.imageName { + self.contentView.image = UIImage(bundleImageName: component.imageName) + } + + self.component = component + + let size = CGSize(width: 28.0, height: 28.0) + + let color = component.isHighlighted ? component.theme.chat.inputMediaPanel.panelHighlightedIconColor : component.theme.chat.inputMediaPanel.panelIconColor + + if self.contentView.tintColor != color { + if !transition.animation.isImmediate { + UIView.animate(withDuration: 0.15, delay: 0.0, options: [], animations: { + self.contentView.tintColor = color + }, completion: nil) + } else { + self.contentView.tintColor = color + } + } + + let contentSize = self.contentView.image?.size ?? size + transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(x: floor((size.width - contentSize.width) / 2.0), y: (size.height - contentSize.height) / 2.0), size: contentSize)) + + return size + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +final class EntityKeyboardBottomPanelComponent: Component { + typealias EnvironmentType = PagerComponentPanelEnvironment + + let theme: PresentationTheme + let containerInsets: UIEdgeInsets + let deleteBackwards: () -> Void + + init( + theme: PresentationTheme, + containerInsets: UIEdgeInsets, + deleteBackwards: @escaping () -> Void + ) { + self.theme = theme + self.containerInsets = containerInsets + self.deleteBackwards = deleteBackwards + } + + static func ==(lhs: EntityKeyboardBottomPanelComponent, rhs: EntityKeyboardBottomPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.containerInsets != rhs.containerInsets { + return false + } + + return true + } + + final class View: UIView { + private final class AccessoryButtonView { + let id: AnyHashable + var component: AnyComponent + let view: ComponentHostView + + init(id: AnyHashable, component: AnyComponent, view: ComponentHostView) { + self.id = id + self.component = component + self.view = view + } + } + + private let backgroundView: BlurredBackgroundView + private let separatorView: UIView + private var leftAccessoryButton: AccessoryButtonView? + private var rightAccessoryButton: AccessoryButtonView? + + private var iconViews: [AnyHashable: ComponentHostView] = [:] + private var highlightedIconBackgroundView: UIView + + private var component: EntityKeyboardBottomPanelComponent? + + override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true) + + self.separatorView = UIView() + self.separatorView.isUserInteractionEnabled = false + + self.highlightedIconBackgroundView = UIView() + self.highlightedIconBackgroundView.isUserInteractionEnabled = false + self.highlightedIconBackgroundView.layer.cornerRadius = 10.0 + self.highlightedIconBackgroundView.clipsToBounds = true + + super.init(frame: frame) + + self.addSubview(self.backgroundView) + self.addSubview(self.highlightedIconBackgroundView) + self.addSubview(self.separatorView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: EntityKeyboardBottomPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + if self.component?.theme !== component.theme { + self.separatorView.backgroundColor = component.theme.chat.inputMediaPanel.panelSeparatorColor + self.backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(1.0), transition: .immediate) + self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor + } + + let intrinsicHeight: CGFloat = 34.0 + let height = intrinsicHeight + component.containerInsets.bottom + + let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value + let activeContentId = panelEnvironment.activeContentId + + var leftAccessoryButtonComponent: AnyComponentWithIdentity? + for contentAccessoryLeftButton in panelEnvironment.contentAccessoryLeftButtons { + if contentAccessoryLeftButton.id == activeContentId { + leftAccessoryButtonComponent = contentAccessoryLeftButton + break + } + } + let previousLeftAccessoryButton = self.leftAccessoryButton + + if let leftAccessoryButtonComponent = leftAccessoryButtonComponent { + var leftAccessoryButtonTransition = transition + let leftAccessoryButton: AccessoryButtonView + if let current = self.leftAccessoryButton, (current.id == leftAccessoryButtonComponent.id || current.component == leftAccessoryButtonComponent.component) { + leftAccessoryButton = current + leftAccessoryButton.component = leftAccessoryButtonComponent.component + } else { + leftAccessoryButtonTransition = .immediate + leftAccessoryButton = AccessoryButtonView(id: leftAccessoryButtonComponent.id, component: leftAccessoryButtonComponent.component, view: ComponentHostView()) + self.leftAccessoryButton = leftAccessoryButton + self.addSubview(leftAccessoryButton.view) + } + + let leftAccessoryButtonSize = leftAccessoryButton.view.update( + transition: leftAccessoryButtonTransition, + component: leftAccessoryButtonComponent.component, + environment: {}, + containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) + ) + leftAccessoryButtonTransition.setFrame(view: leftAccessoryButton.view, frame: CGRect(origin: CGPoint(x: component.containerInsets.left + 2.0, y: 2.0), size: leftAccessoryButtonSize)) + } else { + self.leftAccessoryButton = nil + } + + if previousLeftAccessoryButton?.view !== self.leftAccessoryButton?.view { + if case .none = transition.animation { + previousLeftAccessoryButton?.view.removeFromSuperview() + } else { + if let previousLeftAccessoryButton = previousLeftAccessoryButton { + let previousLeftAccessoryButtonView = previousLeftAccessoryButton.view + previousLeftAccessoryButtonView.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) + previousLeftAccessoryButtonView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousLeftAccessoryButtonView] _ in + previousLeftAccessoryButtonView?.removeFromSuperview() + }) + } + + if let leftAccessoryButtonView = self.leftAccessoryButton?.view { + leftAccessoryButtonView.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2) + leftAccessoryButtonView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } + } + + var rightAccessoryButtonComponent: AnyComponentWithIdentity? + for contentAccessoryRightButton in panelEnvironment.contentAccessoryRightButtons { + if contentAccessoryRightButton.id == activeContentId { + rightAccessoryButtonComponent = contentAccessoryRightButton + break + } + } + let previousRightAccessoryButton = self.rightAccessoryButton + + if let rightAccessoryButtonComponent = rightAccessoryButtonComponent { + var rightAccessoryButtonTransition = transition + let rightAccessoryButton: AccessoryButtonView + if let current = self.rightAccessoryButton, (current.id == rightAccessoryButtonComponent.id || current.component == rightAccessoryButtonComponent.component) { + rightAccessoryButton = current + current.component = rightAccessoryButtonComponent.component + } else { + rightAccessoryButtonTransition = .immediate + rightAccessoryButton = AccessoryButtonView(id: rightAccessoryButtonComponent.id, component: rightAccessoryButtonComponent.component, view: ComponentHostView()) + self.rightAccessoryButton = rightAccessoryButton + self.addSubview(rightAccessoryButton.view) + } + + let rightAccessoryButtonSize = rightAccessoryButton.view.update( + transition: rightAccessoryButtonTransition, + component: rightAccessoryButtonComponent.component, + environment: {}, + containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) + ) + rightAccessoryButtonTransition.setFrame(view: rightAccessoryButton.view, frame: CGRect(origin: CGPoint(x: availableSize.width - component.containerInsets.right - 2.0 - rightAccessoryButtonSize.width, y: 2.0), size: rightAccessoryButtonSize)) + } else { + self.rightAccessoryButton = nil + } + + if previousRightAccessoryButton?.view !== self.rightAccessoryButton?.view { + if case .none = transition.animation { + previousRightAccessoryButton?.view.removeFromSuperview() + } else { + if let previousRightAccessoryButton = previousRightAccessoryButton { + let previousRightAccessoryButtonView = previousRightAccessoryButton.view + previousRightAccessoryButtonView.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) + previousRightAccessoryButtonView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousRightAccessoryButtonView] _ in + previousRightAccessoryButtonView?.removeFromSuperview() + }) + } + + if let rightAccessoryButtonView = self.rightAccessoryButton?.view { + rightAccessoryButtonView.layer.animateScale(from: 0.01, to: 1.0, duration: 0.2) + rightAccessoryButtonView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } + } + + var validIconIds: [AnyHashable] = [] + var iconInfos: [AnyHashable: (size: CGSize, transition: Transition)] = [:] + + var iconTotalSize = CGSize() + let iconSpacing: CGFloat = 22.0 + + let navigateToContentId = panelEnvironment.navigateToContentId + + if panelEnvironment.contentIcons.count > 1 { + for icon in panelEnvironment.contentIcons { + validIconIds.append(icon.id) + + var iconTransition = transition + let iconView: ComponentHostView + if let current = self.iconViews[icon.id] { + iconView = current + } else { + iconTransition = .immediate + iconView = ComponentHostView() + self.iconViews[icon.id] = iconView + self.addSubview(iconView) + } + + let iconSize = iconView.update( + transition: iconTransition, + component: AnyComponent(BottomPanelIconComponent( + imageName: icon.imageName, + isHighlighted: icon.id == activeContentId, + theme: component.theme, + action: { + navigateToContentId(icon.id) + } + )), + environment: {}, + containerSize: CGSize(width: 28.0, height: 28.0) + ) + + iconInfos[icon.id] = (size: iconSize, transition: iconTransition) + + if !iconTotalSize.width.isZero { + iconTotalSize.width += iconSpacing + } + iconTotalSize.width += iconSize.width + iconTotalSize.height = max(iconTotalSize.height, iconSize.height) + } + } + + var nextIconOrigin = CGPoint(x: floor((availableSize.width - iconTotalSize.width) / 2.0), y: floor((intrinsicHeight - iconTotalSize.height) / 2.0)) + if component.containerInsets.bottom > 0.0 { + nextIconOrigin.y += 3.0 + } + + if panelEnvironment.contentIcons.count > 1 { + for icon in panelEnvironment.contentIcons { + guard let iconInfo = iconInfos[icon.id], let iconView = self.iconViews[icon.id] else { + continue + } + + let iconFrame = CGRect(origin: nextIconOrigin, size: iconInfo.size) + iconInfo.transition.setFrame(view: iconView, frame: iconFrame, completion: nil) + + if let activeContentId = activeContentId, activeContentId == icon.id { + self.highlightedIconBackgroundView.isHidden = false + transition.setFrame(view: self.highlightedIconBackgroundView, frame: iconFrame) + + let cornerRadius: CGFloat + if icon.id == AnyHashable("emoji") { + cornerRadius = min(iconFrame.width, iconFrame.height) / 2.0 + } else { + cornerRadius = 10.0 + } + transition.setCornerRadius(layer: self.highlightedIconBackgroundView.layer, cornerRadius: cornerRadius) + } + + nextIconOrigin.x += iconInfo.size.width + iconSpacing + } + } + + if activeContentId == nil { + self.highlightedIconBackgroundView.isHidden = true + } + + var removedIconViewIds: [AnyHashable] = [] + for (id, iconView) in self.iconViews { + if !validIconIds.contains(id) { + removedIconViewIds.append(id) + iconView.removeFromSuperview() + } + } + for id in removedIconViewIds { + self.iconViews.removeValue(forKey: id) + } + + transition.setFrame(view: self.separatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: UIScreenPixel))) + + transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: height))) + self.backgroundView.update(size: CGSize(width: availableSize.width, height: height), transition: transition.containedViewLayoutTransition) + + self.component = component + + return CGSize(width: availableSize.width, height: height) + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift new file mode 100644 index 0000000000..3f7b663927 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -0,0 +1,290 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox + +final class EntityKeyboardTopContainerPanelEnvironment: Equatable { + let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + let isExpandedUpdated: (Bool, Transition) -> Void + + init( + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, + isExpandedUpdated: @escaping (Bool, Transition) -> Void + ) { + self.visibilityFractionUpdated = visibilityFractionUpdated + self.isExpandedUpdated = isExpandedUpdated + } + + static func ==(lhs: EntityKeyboardTopContainerPanelEnvironment, rhs: EntityKeyboardTopContainerPanelEnvironment) -> Bool { + if lhs.visibilityFractionUpdated !== rhs.visibilityFractionUpdated { + return false + } + return true + } +} + +final class EntityKeyboardTopContainerPanelComponent: Component { + typealias EnvironmentType = PagerComponentPanelEnvironment + + let theme: PresentationTheme + let overflowHeight: CGFloat + let displayBackground: Bool + + init( + theme: PresentationTheme, + overflowHeight: CGFloat, + displayBackground: Bool + ) { + self.theme = theme + self.overflowHeight = overflowHeight + self.displayBackground = displayBackground + } + + static func ==(lhs: EntityKeyboardTopContainerPanelComponent, rhs: EntityKeyboardTopContainerPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.overflowHeight != rhs.overflowHeight { + return false + } + if lhs.displayBackground != rhs.displayBackground { + return false + } + + return true + } + + private final class PanelView { + let view = ComponentHostView() + let visibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + var isExpanded: Bool = false + } + + final class View: UIView { + private var backgroundView: BlurredBackgroundView? + private var backgroundSeparatorView: UIView? + + private var panelViews: [AnyHashable: PanelView] = [:] + + private var component: EntityKeyboardTopContainerPanelComponent? + private var panelEnvironment: PagerComponentPanelEnvironment? + private weak var state: EmptyComponentState? + + private var visibilityFraction: CGFloat = 1.0 + + override init(frame: CGRect) { + super.init(frame: frame) + + self.disablesInteractiveKeyboardGestureRecognizer = true + self.disablesInteractiveTransitionGestureRecognizer = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: EntityKeyboardTopContainerPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let intrinsicHeight: CGFloat = 34.0 + let height = intrinsicHeight + + let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value + + var transitionOffsetFraction: CGFloat = 0.0 + if case .none = transition.animation { + } else if let previousPanelEnvironment = self.panelEnvironment, let previousActiveContentId = previousPanelEnvironment.activeContentId, let activeContentId = panelEnvironment.activeContentId, previousActiveContentId != activeContentId { + if let previousIndex = panelEnvironment.contentTopPanels.firstIndex(where: { $0.id == previousActiveContentId }), let index = panelEnvironment.contentTopPanels.firstIndex(where: { $0.id == activeContentId }), previousIndex != index { + if index < previousIndex { + transitionOffsetFraction = -1.0 + } else { + transitionOffsetFraction = 1.0 + } + } + } + + self.component = component + self.panelEnvironment = panelEnvironment + self.state = state + + var validPanelIds = Set() + let visibleBounds = CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: intrinsicHeight)) + if let centralId = panelEnvironment.activeContentId, let centralIndex = panelEnvironment.contentTopPanels.firstIndex(where: { $0.id == centralId }) { + for index in 0 ..< panelEnvironment.contentTopPanels.count { + let panel = panelEnvironment.contentTopPanels[index] + let indexOffset = index - centralIndex + + let panelFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * availableSize.width, y: -component.overflowHeight), size: CGSize(width: availableSize.width, height: intrinsicHeight + component.overflowHeight)) + + let isInBounds = visibleBounds.intersects(panelFrame) + let isPartOfTransition: Bool + if !transitionOffsetFraction.isZero && self.panelViews[panel.id] != nil { + isPartOfTransition = true + } else { + isPartOfTransition = false + } + + if isInBounds || isPartOfTransition { + validPanelIds.insert(panel.id) + + var panelTransition = transition + let panelView: PanelView + if let current = self.panelViews[panel.id] { + panelView = current + } else { + panelTransition = .immediate + panelView = PanelView() + self.panelViews[panel.id] = panelView + self.addSubview(panelView.view) + } + + let panelId = panel.id + let _ = panelView.view.update( + transition: panelTransition, + component: panel.component, + environment: { + EntityKeyboardTopContainerPanelEnvironment( + visibilityFractionUpdated: panelView.visibilityFractionUpdated, + isExpandedUpdated: { [weak self] isExpanded, transition in + guard let strongSelf = self else { + return + } + strongSelf.panelIsExpandedUpdated(id: panelId, isExpanded: isExpanded, transition: transition) + } + ) + }, + containerSize: panelFrame.size + ) + if isInBounds { + transition.animatePosition(view: panelView.view, from: CGPoint(x: transitionOffsetFraction * availableSize.width, y: 0.0), to: CGPoint(), additive: true, completion: nil) + } + panelTransition.setFrame(view: panelView.view, frame: panelFrame, completion: { [weak self] completed in + if isPartOfTransition && completed { + self?.state?.updated(transition: .immediate) + } + }) + } + } + } + var removedPanelIds: [AnyHashable] = [] + for (id, panelView) in self.panelViews { + if !validPanelIds.contains(id) { + removedPanelIds.append(id) + panelView.view.removeFromSuperview() + } + } + for id in removedPanelIds { + self.panelViews.removeValue(forKey: id) + } + + environment[PagerComponentPanelEnvironment.self].value.visibilityFractionUpdated.connect { [weak self] (fraction, transition) in + guard let strongSelf = self else { + return + } + strongSelf.updateVisibilityFraction(value: fraction, transition: transition) + } + + if component.displayBackground { + let backgroundView: BlurredBackgroundView + if let current = self.backgroundView { + backgroundView = current + } else { + backgroundView = BlurredBackgroundView(color: .clear, enableBlur: true) + self.insertSubview(backgroundView, at: 0) + } + + let backgroundSeparatorView: UIView + if let current = self.backgroundSeparatorView { + backgroundSeparatorView = current + } else { + backgroundSeparatorView = UIView() + self.insertSubview(backgroundSeparatorView, aboveSubview: backgroundView) + } + + backgroundView.updateColor(color: component.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(1.0), transition: .immediate) + backgroundView.update(size: CGSize(width: availableSize.width, height: height), transition: transition.containedViewLayoutTransition) + transition.setFrame(view: backgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: height))) + + backgroundSeparatorView.backgroundColor = component.theme.chat.inputPanel.panelSeparatorColor + transition.setFrame(view: backgroundSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: height), size: CGSize(width: availableSize.width, height: UIScreenPixel))) + } else { + if let backgroundView = self.backgroundView { + self.backgroundView = nil + backgroundView.removeFromSuperview() + } + if let backgroundSeparatorView = self.backgroundSeparatorView { + self.backgroundSeparatorView = nil + backgroundSeparatorView.removeFromSuperview() + } + } + + return CGSize(width: availableSize.width, height: height) + } + + private func updateVisibilityFraction(value: CGFloat, transition: Transition) { + if self.visibilityFraction == value { + return + } + + self.visibilityFraction = value + for (_, panelView) in self.panelViews { + panelView.visibilityFractionUpdated.invoke((value, transition)) + transition.setSublayerTransform(view: panelView.view, transform: CATransform3DMakeTranslation(0.0, -panelView.view.bounds.height / 2.0 * (1.0 - value), 0.0)) + } + } + + private func panelIsExpandedUpdated(id: AnyHashable, isExpanded: Bool, transition: Transition) { + guard let panelView = self.panelViews[id] else { + return + } + if panelView.isExpanded == isExpanded { + return + } + panelView.isExpanded = isExpanded + + var hasExpanded = false + for (_, panel) in self.panelViews { + if panel.isExpanded { + hasExpanded = true + break + } + } + + self.panelEnvironment?.isExpandedUpdated(hasExpanded, transition) + } + + public func internalUpdatePanelsAreCollapsed() { + for (_, panelView) in self.panelViews { + panelView.isExpanded = false + } + } + + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.alpha.isZero { + return nil + } + for view in self.subviews.reversed() { + if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled { + return result + } + } + + let result = super.hitTest(point, with: event) + if result != self { + return result + } else { + return nil + } + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift new file mode 100644 index 0000000000..1c4f0fe10e --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -0,0 +1,1956 @@ +import Foundation +import SwiftSignalKit +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import AnimationCache +import MultiAnimationRenderer +import AccountContext +import MultilineTextComponent +import LottieAnimationComponent + +final class EntityKeyboardAnimationTopPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment + + let context: AccountContext + let file: TelegramMediaFile + let isFeatured: Bool + let isPremiumLocked: Bool + let animationCache: AnimationCache + let animationRenderer: MultiAnimationRenderer + let theme: PresentationTheme + let title: String + let pressed: () -> Void + + init( + context: AccountContext, + file: TelegramMediaFile, + isFeatured: Bool, + isPremiumLocked: Bool, + animationCache: AnimationCache, + animationRenderer: MultiAnimationRenderer, + theme: PresentationTheme, + title: String, + pressed: @escaping () -> Void + ) { + self.context = context + self.file = file + self.isFeatured = isFeatured + self.isPremiumLocked = isPremiumLocked + self.animationCache = animationCache + self.animationRenderer = animationRenderer + self.theme = theme + self.title = title + self.pressed = pressed + } + + static func ==(lhs: EntityKeyboardAnimationTopPanelComponent, rhs: EntityKeyboardAnimationTopPanelComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.file.fileId != rhs.file.fileId { + return false + } + if lhs.isFeatured != rhs.isFeatured { + return false + } + if lhs.isPremiumLocked != rhs.isPremiumLocked { + return false + } + if lhs.animationCache !== rhs.animationCache { + return false + } + if lhs.animationRenderer !== rhs.animationRenderer { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.title != rhs.title { + return false + } + + return true + } + + final class View: UIView { + var itemLayer: EmojiPagerContentComponent.View.ItemLayer? + var placeholderView: EmojiPagerContentComponent.View.ItemPlaceholderView? + var component: EntityKeyboardAnimationTopPanelComponent? + var titleView: ComponentView? + + override init(frame: CGRect) { + super.init(frame: frame) + + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.component?.pressed() + } + } + + func update(component: EntityKeyboardAnimationTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + + let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value + + let dimensions = component.file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0) + let displaySize = dimensions.aspectFitted(CGSize(width: 44.0, height: 44.0)) + + if self.itemLayer == nil { + let itemLayer = EmojiPagerContentComponent.View.ItemLayer( + item: EmojiPagerContentComponent.Item( + file: component.file, + staticEmoji: nil, + subgroupId: nil + ), + context: component.context, + attemptSynchronousLoad: false, + file: component.file, + staticEmoji: nil, + cache: component.animationCache, + renderer: component.animationRenderer, + placeholderColor: .lightGray, + blurredBadgeColor: .clear, + pointSize: displaySize, + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in + guard let strongSelf = self else { + return + } + strongSelf.updateDisplayPlaceholder(displayPlaceholder: displayPlaceholder, duration: duration) + } + ) + self.itemLayer = itemLayer + self.layer.addSublayer(itemLayer) + + if itemLayer.displayPlaceholder { + self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0) + } + } + + let iconFitSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 24.0, height: 24.0) + let iconSize = dimensions.aspectFitted(iconFitSize) + let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) / 2.0), y: floor((iconFitSize.height - iconSize.height) / 2.0)), size: iconSize).insetBy(dx: -1.0, dy: -1.0) + + if let itemLayer = self.itemLayer { + transition.setPosition(layer: itemLayer, position: CGPoint(x: iconFrame.midX, y: iconFrame.midY)) + transition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: iconFrame.size)) + + var badge: EmojiPagerContentComponent.View.ItemLayer.Badge? + if component.isPremiumLocked { + badge = .locked + } else if component.isFeatured { + badge = .featured + } + itemLayer.update(transition: transition, size: iconFrame.size, badge: badge, blurredBadgeColor: UIColor(white: 0.0, alpha: 0.1), blurredBadgeBackgroundColor: component.theme.list.plainBackgroundColor) + + itemLayer.isVisibleForAnimations = true + } + + if itemEnvironment.isExpanded { + let titleView: ComponentView + if let current = self.titleView { + titleView = current + } else { + titleView = ComponentView() + self.titleView = titleView + } + let titleSize = titleView.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.title, font: Font.regular(10.0), textColor: component.theme.chat.inputPanel.primaryTextColor)), + insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + )), + environment: {}, + containerSize: CGSize(width: 62.0, height: 100.0) + ) + if let view = titleView.view { + if view.superview == nil { + view.alpha = 0.0 + self.addSubview(view) + } + view.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: availableSize.height - titleSize.height - 1.0), size: titleSize) + transition.setAlpha(view: view, alpha: 1.0) + } + } else if let titleView = self.titleView { + self.titleView = nil + if let view = titleView.view { + if !transition.animation.isImmediate { + view.alpha = 0.0 + view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } else { + view.removeFromSuperview() + } + } + } + + return availableSize + } + + private func updateDisplayPlaceholder(displayPlaceholder: Bool, duration: Double) { + if displayPlaceholder { + if self.placeholderView == nil, let component = self.component { + let placeholderView = EmojiPagerContentComponent.View.ItemPlaceholderView( + context: component.context, + file: component.file, + shimmerView: nil, + color: component.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08), + size: CGSize(width: 28.0, height: 28.0) + ) + self.placeholderView = placeholderView + self.insertSubview(placeholderView, at: 0) + placeholderView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 28.0, height: 28.0)) + placeholderView.update(size: CGSize(width: 28.0, height: 28.0)) + } + } else { + if let placeholderView = self.placeholderView { + self.placeholderView = nil + + if duration > 0.0 { + placeholderView.alpha = 0.0 + placeholderView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, completion: { [weak placeholderView] _ in + placeholderView?.removeFromSuperview() + }) + } else { + placeholderView.removeFromSuperview() + } + } + } + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +final class EntityKeyboardIconTopPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment + + enum Icon { + case featured + case trending + case recent + case saved + case premium + } + + let icon: Icon + let theme: PresentationTheme + let title: String + let pressed: () -> Void + + init( + icon: Icon, + theme: PresentationTheme, + title: String, + pressed: @escaping () -> Void + ) { + self.icon = icon + self.theme = theme + self.title = title + self.pressed = pressed + } + + static func ==(lhs: EntityKeyboardIconTopPanelComponent, rhs: EntityKeyboardIconTopPanelComponent) -> Bool { + if lhs.icon != rhs.icon { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.title != rhs.title { + return false + } + + return true + } + + final class View: UIView { + let iconView: UIImageView + var component: EntityKeyboardIconTopPanelComponent? + var titleView: ComponentView? + + override init(frame: CGRect) { + self.iconView = UIImageView() + + super.init(frame: frame) + + self.addSubview(self.iconView) + + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + self.component?.pressed() + } + } + + func update(component: EntityKeyboardIconTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value + + if self.component?.icon != component.icon { + var image: UIImage? + switch component.icon { + case .featured: + image = UIImage(bundleImageName: "Chat/Input/Media/PanelFeaturedIcon") + case .trending: + image = UIImage(bundleImageName: "Chat/Input/Media/PanelTrendingIcon") + case .recent: + image = UIImage(bundleImageName: "Chat/Input/Media/PanelRecentIcon") + case .saved: + image = UIImage(bundleImageName: "Chat/Input/Media/PanelSavedIcon") + case .premium: + image = generateImage(CGSize(width: 44.0, height: 44.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let image = UIImage(bundleImageName: "Chat/Input/Media/EntityInputPremiumIcon") { + if let cgImage = image.cgImage { + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + } + + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x6B93FF).cgColor, + UIColor(rgb: 0x6B93FF).cgColor, + UIColor(rgb: 0x976FFF).cgColor, + UIColor(rgb: 0xE46ACE).cgColor, + UIColor(rgb: 0xE46ACE).cgColor + ] + var locations: [CGFloat] = [0.0, 0.35, 0.5, 0.65, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + } + }) + } + + self.iconView.image = image + } + + self.component = component + + let color = itemEnvironment.isHighlighted ? component.theme.chat.inputMediaPanel.panelHighlightedIconColor : component.theme.chat.inputMediaPanel.panelIconColor + + if self.iconView.tintColor != color { + if !transition.animation.isImmediate { + UIView.animate(withDuration: 0.15, delay: 0.0, options: [], animations: { + self.iconView.tintColor = color + }, completion: nil) + } else { + self.iconView.tintColor = color + } + } + + let nativeIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 24.0, height: 24.0) + let boundingIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 38.0, height: 38.0) : CGSize(width: 24.0, height: 24.0) + + let iconSize = (self.iconView.image?.size ?? nativeIconSize).aspectFitted(boundingIconSize) + let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) / 2.0), y: floor((nativeIconSize.height - iconSize.height) / 2.0)), size: iconSize) + + transition.setFrame(view: self.iconView, frame: iconFrame) + + if itemEnvironment.isExpanded { + let titleView: ComponentView + if let current = self.titleView { + titleView = current + } else { + titleView = ComponentView() + self.titleView = titleView + } + let titleSize = titleView.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.title, font: Font.regular(10.0), textColor: component.theme.chat.inputPanel.primaryTextColor)), + insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + )), + environment: {}, + containerSize: CGSize(width: 62.0, height: 100.0) + ) + if let view = titleView.view { + if view.superview == nil { + view.alpha = 0.0 + self.addSubview(view) + } + view.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: availableSize.height - titleSize.height - 1.0), size: titleSize) + transition.setAlpha(view: view, alpha: 1.0) + } + } else if let titleView = self.titleView { + self.titleView = nil + if let view = titleView.view { + if !transition.animation.isImmediate { + view.alpha = 0.0 + view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } else { + view.removeFromSuperview() + } + } + } + + return availableSize + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +final class EntityKeyboardStaticStickersPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment + + let theme: PresentationTheme + let title: String + let pressed: (EmojiPagerContentComponent.StaticEmojiSegment) -> Void + + init( + theme: PresentationTheme, + title: String, + pressed: @escaping (EmojiPagerContentComponent.StaticEmojiSegment) -> Void + ) { + self.theme = theme + self.title = title + self.pressed = pressed + } + + static func ==(lhs: EntityKeyboardStaticStickersPanelComponent, rhs: EntityKeyboardStaticStickersPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.title != rhs.title { + return false + } + + return true + } + + final class View: UIView, UIScrollViewDelegate { + private struct ItemLayout { + var isExpanded: Bool + var isActive: Bool + var baseItemSize: CGFloat + var itemSize: CGFloat + var itemSpacing: CGFloat + var sideInset: CGFloat + var itemOffset: CGFloat + var contentSize: CGSize + + init(isExpanded: Bool, isActive: Bool, width: CGFloat, height: CGFloat, itemCount: Int) { + self.isExpanded = isExpanded + self.isActive = isActive + self.baseItemSize = 42.0 + self.itemSize = isExpanded ? self.baseItemSize : 26.0 + self.itemSpacing = 4.0 + self.sideInset = isExpanded ? 5.0 : 2.0 + self.itemOffset = isExpanded ? -8.0 : 0.0 + self.contentSize = CGSize(width: self.sideInset * 2.0 + CGFloat(itemCount) * self.itemSize + CGFloat(itemCount - 1) * self.itemSpacing, height: height) + } + + func frame(at index: Int) -> CGRect { + var frame = CGRect(origin: CGPoint(x: self.sideInset + CGFloat(index) * (self.itemSize + self.itemSpacing), y: floor(self.contentSize.height - self.itemSize) / 2.0 + self.itemOffset), size: CGSize(width: self.itemSize, height: self.itemSize)) + if self.isActive && !self.isExpanded { + frame = frame.insetBy(dx: 2.0, dy: 2.0) + } + return frame + } + } + + private let scrollViewContainer: UIView + private let scrollView: UIScrollView + private var visibleItemViews: [EmojiPagerContentComponent.StaticEmojiSegment: ComponentView] = [:] + + private var titleView: ComponentView? + + private var component: EntityKeyboardStaticStickersPanelComponent? + private var itemEnvironment: EntityKeyboardTopPanelItemEnvironment? + + private var itemLayout: ItemLayout? + + private var ignoreScrolling: Bool = false + + override init(frame: CGRect) { + self.scrollViewContainer = UIView() + self.scrollViewContainer.clipsToBounds = true + + self.scrollView = UIScrollView() + + super.init(frame: frame) + + self.scrollView.layer.anchorPoint = CGPoint() + self.scrollView.delaysContentTouches = false + self.scrollView.clipsToBounds = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollView.contentInsetAdjustmentBehavior = .never + } + if #available(iOS 13.0, *) { + self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + self.scrollView.showsVerticalScrollIndicator = false + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.alwaysBounceHorizontal = false + self.scrollView.scrollsToTop = false + self.scrollView.delegate = self + self.scrollView.clipsToBounds = false + + self.scrollViewContainer.addSubview(self.scrollView) + self.addSubview(self.scrollViewContainer) + + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + if !self.bounds.contains(recognizer.location(in: self)) { + return + } + let scrollViewLocation = recognizer.location(in: self.scrollView) + var closestItem: (distance: CGFloat, id: EmojiPagerContentComponent.StaticEmojiSegment)? + for (id, itemView) in self.visibleItemViews { + if let view = itemView.view { + let distance = abs(view.center.x - scrollViewLocation.x) + if let closestItemValue = closestItem { + if distance < closestItemValue.distance { + closestItem = (distance, id) + } + } else { + closestItem = (distance, id) + } + } + } + + if let closestItem = closestItem { + self.component?.pressed(closestItem.id) + } + } + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + self.updateVisibleItems(transition: .immediate, animateAppearingItems: true) + } + + private func updateVisibleItems(transition: Transition, animateAppearingItems: Bool) { + guard let component = self.component, let itemEnvironment = self.itemEnvironment, let itemLayout = self.itemLayout else { + return + } + + var validItemIds = Set() + let visibleBounds = self.scrollView.bounds + + let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases + for i in 0 ..< items.count { + let itemFrame = itemLayout.frame(at: i) + if true/*visibleBounds.intersects(itemFrame)*/ { + let item = items[i] + validItemIds.insert(item) + + var animateItem = false + var itemTransition = transition + let itemView: ComponentView + if let current = self.visibleItemViews[item] { + itemView = current + } else { + animateItem = animateAppearingItems + itemTransition = .immediate + itemView = ComponentView() + self.visibleItemViews[item] = itemView + } + let _ = animateItem + + let animationName: String + switch item { + case .people: + animationName = "emojicat_smiles" + case .animalsAndNature: + animationName = "emojicat_animals" + case .foodAndDrink: + animationName = "emojicat_food" + case .activityAndSport: + animationName = "emojicat_activity" + case .travelAndPlaces: + animationName = "emojicat_places" + case .objects: + animationName = "emojicat_objects" + case .symbols: + animationName = "emojicat_symbols" + case .flags: + animationName = "emojicat_flags" + } + + let baseColor: UIColor + if itemEnvironment.highlightedSubgroupId == AnyHashable(items[i].rawValue) { + baseColor = component.theme.chat.inputMediaPanel.panelHighlightedIconColor + } else { + baseColor = component.theme.chat.inputMediaPanel.panelIconColor + } + + let baseHighlightedColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor.blitOver(component.theme.chat.inputPanel.panelBackgroundColor, alpha: 1.0) + let color = baseColor.blitOver(baseHighlightedColor, alpha: 1.0) + + let _ = itemTransition + let _ = itemView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: animationName, + mode: .still(position: .end) + ), + colors: ["__allcolors__": color], + size: CGSize(width: itemLayout.baseItemSize, height: itemLayout.baseItemSize) + )), + environment: {}, + containerSize: CGSize(width: itemLayout.baseItemSize, height: itemLayout.baseItemSize) + ) + if let view = itemView.view { + if view.superview == nil { + self.scrollView.addSubview(view) + } + + itemTransition.setPosition(view: view, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) + itemTransition.setBounds(view: view, bounds: CGRect(origin: CGPoint(), size: CGSize(width: itemLayout.baseItemSize, height: itemLayout.baseItemSize))) + let scaleFactor = itemFrame.width / itemLayout.baseItemSize + itemTransition.setSublayerTransform(view: view, transform: CATransform3DMakeScale(scaleFactor, scaleFactor, 1.0)) + + let isHidden = !visibleBounds.intersects(itemFrame) + if isHidden != view.isHidden { + view.isHidden = isHidden + + if !isHidden { + if let view = view as? LottieAnimationComponent.View { + view.playOnce() + } + } + } + } + } + } + + var removedItemIds: [EmojiPagerContentComponent.StaticEmojiSegment] = [] + for (id, itemView) in self.visibleItemViews { + if !validItemIds.contains(id) { + removedItemIds.append(id) + itemView.view?.removeFromSuperview() + } + } + for id in removedItemIds { + self.visibleItemViews.removeValue(forKey: id) + } + } + + func update(component: EntityKeyboardStaticStickersPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value + + var scrollToItem: AnyHashable? + if itemEnvironment.highlightedSubgroupId != self.itemEnvironment?.highlightedSubgroupId { + scrollToItem = itemEnvironment.highlightedSubgroupId + } + + self.component = component + self.itemEnvironment = itemEnvironment + + let itemLayout = ItemLayout(isExpanded: itemEnvironment.isExpanded, isActive: itemEnvironment.isHighlighted, width: availableSize.width, height: availableSize.height, itemCount: EmojiPagerContentComponent.StaticEmojiSegment.allCases.count) + self.itemLayout = itemLayout + + transition.setFrame(view: self.scrollViewContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height))) + transition.setCornerRadius(layer: self.scrollViewContainer.layer, cornerRadius: min(availableSize.width / 2.0, availableSize.height / 2.0)) + + self.ignoreScrolling = true + self.scrollView.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(availableSize.width, 0.0), height: availableSize.height)) + self.scrollView.contentSize = itemLayout.contentSize + self.ignoreScrolling = false + + self.updateVisibleItems(transition: transition, animateAppearingItems: false) + + if (!itemEnvironment.isHighlighted || itemLayout.isExpanded) && self.scrollView.contentOffset.x != 0.0 { + self.scrollView.setContentOffset(CGPoint(), animated: true) + scrollToItem = nil + } + + self.scrollView.isUserInteractionEnabled = itemEnvironment.isHighlighted && !itemLayout.isExpanded + + if let scrollToItem = scrollToItem { + let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases + for i in 0 ..< items.count { + if AnyHashable(items[i].rawValue) == scrollToItem { + let itemFrame = itemLayout.frame(at: i) + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -itemLayout.sideInset - (itemLayout.itemSpacing + itemFrame.width) * 2.0, dy: 0.0), animated: true) + break + } + } + } + + if itemEnvironment.isExpanded { + let titleView: ComponentView + if let current = self.titleView { + titleView = current + } else { + titleView = ComponentView() + self.titleView = titleView + } + let titleSize = titleView.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.title, font: Font.regular(10.0), textColor: component.theme.chat.inputPanel.primaryTextColor)), + insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0) + )), + environment: {}, + containerSize: CGSize(width: 62.0, height: 100.0) + ) + if let view = titleView.view { + if view.superview == nil { + view.alpha = 0.0 + self.addSubview(view) + } + view.frame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: availableSize.height - titleSize.height - 4.0), size: titleSize) + transition.setAlpha(view: view, alpha: 1.0) + } + } else if let titleView = self.titleView { + self.titleView = nil + if let view = titleView.view { + if !transition.animation.isImmediate { + view.alpha = 0.0 + view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } else { + view.removeFromSuperview() + } + } + } + + return availableSize + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} + +final class EntityKeyboardTopPanelItemEnvironment: Equatable { + let isExpanded: Bool + let isHighlighted: Bool + let highlightedSubgroupId: AnyHashable? + + init(isExpanded: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { + self.isExpanded = isExpanded + self.isHighlighted = isHighlighted + self.highlightedSubgroupId = highlightedSubgroupId + } + + static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { + if lhs.isExpanded != rhs.isExpanded { + return false + } + if lhs.isHighlighted != rhs.isHighlighted { + return false + } + if lhs.highlightedSubgroupId != rhs.highlightedSubgroupId { + return false + } + return true + } +} + +private final class ReorderGestureRecognizer: UIGestureRecognizer { + private let shouldBegin: (CGPoint) -> (allowed: Bool, requiresLongPress: Bool, itemView: ComponentHostView?) + private let willBegin: (CGPoint) -> Void + private let began: (ComponentHostView) -> Void + private let ended: () -> Void + private let moved: (CGFloat) -> Void + private let isActiveUpdated: (Bool) -> Void + + private var initialLocation: CGPoint? + private var longTapTimer: SwiftSignalKit.Timer? + private var longPressTimer: SwiftSignalKit.Timer? + + private var itemView: ComponentHostView? + + public init(shouldBegin: @escaping (CGPoint) -> (allowed: Bool, requiresLongPress: Bool, itemView: ComponentHostView?), willBegin: @escaping (CGPoint) -> Void, began: @escaping (ComponentHostView) -> Void, ended: @escaping () -> Void, moved: @escaping (CGFloat) -> Void, isActiveUpdated: @escaping (Bool) -> Void) { + self.shouldBegin = shouldBegin + self.willBegin = willBegin + self.began = began + self.ended = ended + self.moved = moved + self.isActiveUpdated = isActiveUpdated + + super.init(target: nil, action: nil) + } + + deinit { + self.longTapTimer?.invalidate() + self.longPressTimer?.invalidate() + } + + private func startLongTapTimer() { + self.longTapTimer?.invalidate() + let longTapTimer = SwiftSignalKit.Timer(timeout: 0.25, repeat: false, completion: { [weak self] in + self?.longTapTimerFired() + }, queue: Queue.mainQueue()) + self.longTapTimer = longTapTimer + longTapTimer.start() + } + + private func stopLongTapTimer() { + self.itemView = nil + self.longTapTimer?.invalidate() + self.longTapTimer = nil + } + + private func startLongPressTimer() { + self.longPressTimer?.invalidate() + let longPressTimer = SwiftSignalKit.Timer(timeout: 0.6, repeat: false, completion: { [weak self] in + self?.longPressTimerFired() + }, queue: Queue.mainQueue()) + self.longPressTimer = longPressTimer + longPressTimer.start() + } + + private func stopLongPressTimer() { + self.itemView = nil + self.longPressTimer?.invalidate() + self.longPressTimer = nil + } + + override public func reset() { + super.reset() + + self.itemView = nil + self.stopLongTapTimer() + self.stopLongPressTimer() + self.initialLocation = nil + + self.isActiveUpdated(false) + } + + private func longTapTimerFired() { + guard let location = self.initialLocation else { + return + } + + self.longTapTimer?.invalidate() + self.longTapTimer = nil + + self.willBegin(location) + } + + private func longPressTimerFired() { + guard let _ = self.initialLocation else { + return + } + + self.isActiveUpdated(true) + self.state = .began + self.longPressTimer?.invalidate() + self.longPressTimer = nil + self.longTapTimer?.invalidate() + self.longTapTimer = nil + if let itemView = self.itemView { + self.began(itemView) + } + self.isActiveUpdated(true) + } + + override public func touchesBegan(_ touches: Set, with event: UIEvent) { + super.touchesBegan(touches, with: event) + + if self.numberOfTouches > 1 { + self.isActiveUpdated(false) + self.state = .failed + self.ended() + return + } + + if self.state == .possible { + if let location = touches.first?.location(in: self.view) { + let (allowed, requiresLongPress, itemView) = self.shouldBegin(location) + if allowed { + self.isActiveUpdated(true) + + self.itemView = itemView + self.initialLocation = location + if requiresLongPress { + self.startLongTapTimer() + self.startLongPressTimer() + } else { + self.state = .began + if let itemView = self.itemView { + self.began(itemView) + } + } + } else { + self.isActiveUpdated(false) + self.state = .failed + } + } else { + self.isActiveUpdated(false) + self.state = .failed + } + } + } + + override public func touchesEnded(_ touches: Set, with event: UIEvent) { + super.touchesEnded(touches, with: event) + + self.initialLocation = nil + + self.stopLongTapTimer() + if self.longPressTimer != nil { + self.stopLongPressTimer() + self.isActiveUpdated(false) + self.state = .failed + } + if self.state == .began || self.state == .changed { + self.isActiveUpdated(false) + self.ended() + self.state = .failed + } + } + + override public func touchesCancelled(_ touches: Set, with event: UIEvent) { + super.touchesCancelled(touches, with: event) + + self.initialLocation = nil + + self.stopLongTapTimer() + if self.longPressTimer != nil { + self.isActiveUpdated(false) + self.stopLongPressTimer() + self.state = .failed + } + if self.state == .began || self.state == .changed { + self.isActiveUpdated(false) + self.ended() + self.state = .failed + } + } + + override public func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) + + if (self.state == .began || self.state == .changed), let initialLocation = self.initialLocation, let location = touches.first?.location(in: self.view) { + self.state = .changed + let offset = location.x - initialLocation.x + self.moved(offset) + } else if let touch = touches.first, let initialTapLocation = self.initialLocation, self.longPressTimer != nil { + let touchLocation = touch.location(in: self.view) + let dX = touchLocation.x - initialTapLocation.x + let dY = touchLocation.y - initialTapLocation.y + + if dX * dX + dY * dY > 3.0 * 3.0 { + self.stopLongTapTimer() + self.stopLongPressTimer() + self.initialLocation = nil + self.isActiveUpdated(false) + self.state = .failed + } + } + } +} + +final class EntityKeyboardTopPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopContainerPanelEnvironment + + final class Item: Equatable { + let id: AnyHashable + let isReorderable: Bool + let content: AnyComponent + + init(id: AnyHashable, isReorderable: Bool, content: AnyComponent) { + self.id = id + self.isReorderable = isReorderable + self.content = content + } + + static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs.id != rhs.id { + return false + } + if lhs.isReorderable != rhs.isReorderable { + return false + } + if lhs.content != rhs.content { + return false + } + + return true + } + } + + let theme: PresentationTheme + let items: [Item] + let containerSideInset: CGFloat + let defaultActiveItemId: AnyHashable? + let forceActiveItemId: AnyHashable? + let activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)> + let reorderItems: ([Item]) -> Void + + init( + theme: PresentationTheme, + items: [Item], + containerSideInset: CGFloat, + defaultActiveItemId: AnyHashable? = nil, + forceActiveItemId: AnyHashable? = nil, + activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>, + reorderItems: @escaping ([Item]) -> Void + ) { + self.theme = theme + self.items = items + self.containerSideInset = containerSideInset + self.defaultActiveItemId = defaultActiveItemId + self.forceActiveItemId = forceActiveItemId + self.activeContentItemIdUpdated = activeContentItemIdUpdated + self.reorderItems = reorderItems + } + + static func ==(lhs: EntityKeyboardTopPanelComponent, rhs: EntityKeyboardTopPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.items != rhs.items { + return false + } + if lhs.containerSideInset != rhs.containerSideInset { + return false + } + if lhs.defaultActiveItemId != rhs.defaultActiveItemId { + return false + } + if lhs.forceActiveItemId != rhs.forceActiveItemId { + return false + } + if lhs.activeContentItemIdUpdated !== rhs.activeContentItemIdUpdated { + return false + } + + return true + } + + final class View: UIView, UIScrollViewDelegate { + private struct ItemLayout { + struct ItemDescription { + var isStatic: Bool + var isStaticExpanded: Bool + } + + struct Item { + var frame: CGRect + var innerFrame: CGRect + } + + let topInset: CGFloat = -3.0 + let sideInset: CGFloat + let itemSize: CGSize + let staticItemSize: CGSize + let staticExpandedItemSize: CGSize + let innerItemSize: CGSize + let itemSpacing: CGFloat + let contentSize: CGSize + let isExpanded: Bool + let items: [Item] + + init(isExpanded: Bool, containerSideInset: CGFloat, height: CGFloat, items: [ItemDescription]) { + self.sideInset = containerSideInset + 7.0 + + self.isExpanded = isExpanded + self.itemSize = self.isExpanded ? CGSize(width: 54.0, height: 68.0) : CGSize(width: 28.0, height: 28.0) + self.staticItemSize = self.itemSize + self.staticExpandedItemSize = self.isExpanded ? self.staticItemSize : CGSize(width: 134.0, height: 28.0) + self.innerItemSize = self.isExpanded ? CGSize(width: 50.0, height: 62.0) : CGSize(width: 24.0, height: 24.0) + self.itemSpacing = 8.0 + + var contentSize = CGSize(width: sideInset, height: height) + var resultItems: [Item] = [] + + var isFirst = true + let itemY = self.topInset + floor((contentSize.height - self.itemSize.height) / 2.0) + for item in items { + if isFirst { + isFirst = false + } else { + contentSize.width += itemSpacing + } + let currentItemSize: CGSize + if item.isStaticExpanded { + currentItemSize = self.staticExpandedItemSize + } else if item.isStatic { + currentItemSize = self.staticItemSize + } else { + currentItemSize = self.itemSize + } + let frame = CGRect(origin: CGPoint(x: contentSize.width, y: itemY), size: currentItemSize) + + var innerFrame = frame + if item.isStaticExpanded { + } else if item.isStatic { + } else { + innerFrame.origin.x += floor((self.itemSize.width - self.innerItemSize.width)) / 2.0 + innerFrame.origin.y += floor((self.itemSize.height - self.innerItemSize.height)) / 2.0 + innerFrame.size = self.innerItemSize + } + + resultItems.append(Item( + frame: frame, + innerFrame: innerFrame + )) + + contentSize.width += frame.width + } + + contentSize.width += sideInset + + self.contentSize = contentSize + self.items = resultItems + } + + func containerFrame(at index: Int) -> CGRect { + return self.items[index].frame + } + + func contentFrame(index: Int, containerFrame: CGRect) -> CGRect { + let outerFrame = self.items[index].frame + let innerFrame = self.items[index].innerFrame + + let sizeDifference = CGSize(width: outerFrame.width - innerFrame.width, height: outerFrame.height - innerFrame.height) + let offsetDifference = CGPoint(x: outerFrame.minX - innerFrame.minX, y: outerFrame.minY - innerFrame.minY) + + var frame = containerFrame + frame.origin.x -= offsetDifference.x + frame.origin.y -= offsetDifference.y + frame.size.width -= sizeDifference.width + frame.size.height -= sizeDifference.height + + return frame + } + + func contentFrame(at index: Int) -> CGRect { + return self.items[index].innerFrame + } + + func visibleItemRange(for rect: CGRect) -> (minIndex: Int, maxIndex: Int) { + for i in 0 ..< self.items.count { + if self.items[i].frame.intersects(rect) { + for j in i ..< self.items.count { + if !self.items[j].frame.intersects(rect) { + return (i, j - 1) + } + } + return (i, self.items.count - 1) + } + } + return (0, -1) + } + } + + private let scrollView: UIScrollView + private var itemViews: [AnyHashable: ComponentHostView] = [:] + private var highlightedIconBackgroundView: UIView + + private var temporaryReorderingOrderIndex: (id: AnyHashable, index: Int)? + + private weak var currentReorderingItemView: ComponentHostView? + private var currentReorderingItemId: AnyHashable? + private var currentReorderingItemContainerView: UIView? + private var initialReorderingItemFrame: CGRect? + private var currentReorderingScrollDisplayLink: ConstantDisplayLinkAnimator? + private lazy var reorderingHapticFeedback: HapticFeedback = { + return HapticFeedback() + }() + + private var itemLayout: ItemLayout? + private var items: [Item] = [] + private var ignoreScrolling: Bool = false + + private var isDragging: Bool = false + private var isReordering: Bool = false + private var isDraggingOrReordering: Bool = false + private var draggingStoppedTimer: SwiftSignalKit.Timer? + private var draggingFocusItemIndex: Int? + private var draggingEndOffset: CGFloat? + + private var isExpanded: Bool = false + + private var visibilityFraction: CGFloat = 1.0 + + private var activeContentItemId: AnyHashable? + private var activeSubcontentItemId: AnyHashable? + + private var reorderGestureRecognizer: ReorderGestureRecognizer? + + private var component: EntityKeyboardTopPanelComponent? + weak var state: EmptyComponentState? + private var environment: EntityKeyboardTopContainerPanelEnvironment? + + override init(frame: CGRect) { + self.scrollView = UIScrollView() + + self.highlightedIconBackgroundView = UIView() + self.highlightedIconBackgroundView.isUserInteractionEnabled = false + self.highlightedIconBackgroundView.clipsToBounds = true + self.highlightedIconBackgroundView.isHidden = true + + super.init(frame: frame) + + self.scrollView.layer.anchorPoint = CGPoint() + self.scrollView.delaysContentTouches = false + self.scrollView.clipsToBounds = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollView.contentInsetAdjustmentBehavior = .never + } + if #available(iOS 13.0, *) { + self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + self.scrollView.showsVerticalScrollIndicator = false + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.alwaysBounceHorizontal = true + self.scrollView.scrollsToTop = false + self.scrollView.delegate = self + self.addSubview(self.scrollView) + + self.scrollView.addSubview(self.highlightedIconBackgroundView) + + self.clipsToBounds = true + + self.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in + guard let strongSelf = self else { + return false + } + return strongSelf.scrollView.contentOffset.x > 0.0 + } + + let reorderGestureRecognizer = ReorderGestureRecognizer( + shouldBegin: { [weak self] point in + guard let strongSelf = self else { + return (false, false, nil) + } + if !strongSelf.isExpanded { + return (false, false, nil) + } + let scrollViewLocation = strongSelf.convert(point, to: strongSelf.scrollView) + for (id, itemView) in strongSelf.itemViews { + if itemView.frame.contains(scrollViewLocation) { + for item in strongSelf.items { + if item.id == id, item.isReorderable { + return (true, true, itemView) + } + } + break + } + } + return (false, false, nil) + }, willBegin: { _ in + }, began: { [weak self] itemView in + guard let strongSelf = self else { + return + } + strongSelf.beginReordering(itemView: itemView) + }, ended: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.endReordering() + }, moved: { [weak self] value in + guard let strongSelf = self else { + return + } + strongSelf.updateReordering(offset: value) + }, isActiveUpdated: { [weak self] isActive in + guard let strongSelf = self else { + return + } + let wasReordering = strongSelf.isReordering + strongSelf.updateIsReordering(isActive) + if !isActive, wasReordering { + strongSelf.endReordering() + } + } + ) + self.reorderGestureRecognizer = reorderGestureRecognizer + self.addGestureRecognizer(reorderGestureRecognizer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + + self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) + } + + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.draggingEndOffset = nil + + if let component = self.component { + var focusItemIndex: Int? + + var location = self.scrollView.panGestureRecognizer.location(in: self.scrollView) + let translation = self.scrollView.panGestureRecognizer.translation(in: self.scrollView) + location.x -= translation.x + location.y -= translation.y + + for (id, itemView) in self.itemViews { + if itemView.frame.insetBy(dx: -4.0, dy: -4.0).contains(location) { + inner: for i in 0 ..< component.items.count { + if id == component.items[i].id { + focusItemIndex = i + break inner + } + } + break + } + } + + self.draggingFocusItemIndex = focusItemIndex + } + + self.updateIsDragging(true) + } + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + self.draggingEndOffset = scrollView.contentOffset.x + + if let component = self.component { + var focusItemIndex: Int? + + var location = self.scrollView.panGestureRecognizer.location(in: self.scrollView) + let translation = self.scrollView.panGestureRecognizer.translation(in: self.scrollView) + location.x -= translation.x + location.y -= translation.y + + for (id, itemView) in self.itemViews { + if itemView.frame.insetBy(dx: -4.0, dy: -4.0).contains(location) { + inner: for i in 0 ..< component.items.count { + if id == component.items[i].id { + focusItemIndex = i + break inner + } + } + break + } + } + + self.draggingFocusItemIndex = focusItemIndex + } + + if !decelerate { + self.updateIsDragging(false) + } + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + self.updateIsDragging(false) + } + + private func updateIsDragging(_ isDragging: Bool) { + self.isDragging = isDragging + self.updateIsDraggingOrReordering() + } + + private func updateIsReordering(_ isReordering: Bool) { + self.isReordering = isReordering + self.updateIsDraggingOrReordering() + } + + private func updateIsDraggingOrReordering() { + let isDraggingOrReordering = self.isDragging || self.isReordering + + if !isDraggingOrReordering { + if !self.isDraggingOrReordering { + return + } + + if self.draggingStoppedTimer == nil { + self.draggingStoppedTimer = SwiftSignalKit.Timer(timeout: 0.8, repeat: false, completion: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.draggingStoppedTimer = nil + strongSelf.isDraggingOrReordering = false + guard let environment = strongSelf.environment else { + return + } + environment.isExpandedUpdated(false, Transition(animation: .curve(duration: 0.3, curve: .spring))) + }, queue: .mainQueue()) + self.draggingStoppedTimer?.start() + } + } else { + self.draggingStoppedTimer?.invalidate() + self.draggingStoppedTimer = nil + + if !self.isDraggingOrReordering { + self.isDraggingOrReordering = true + + guard let environment = self.environment else { + return + } + environment.isExpandedUpdated(true, Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + } + } + + private func beginReordering(itemView: ComponentHostView) { + if let currentReorderingItemView = self.currentReorderingItemView { + if let componentView = currentReorderingItemView.componentView { + currentReorderingItemView.addSubview(componentView) + } + self.currentReorderingItemView = nil + self.currentReorderingItemId = nil + } + + guard let id = self.itemViews.first(where: { $0.value === itemView })?.key else { + return + } + + self.currentReorderingItemId = id + self.currentReorderingItemView = itemView + + let reorderingItemContainerView: UIView + if let current = self.currentReorderingItemContainerView { + reorderingItemContainerView = current + } else { + reorderingItemContainerView = UIView() + self.addSubview(reorderingItemContainerView) + self.currentReorderingItemContainerView = reorderingItemContainerView + } + + reorderingItemContainerView.alpha = 0.5 + reorderingItemContainerView.layer.animateAlpha(from: 1.0, to: 0.5, duration: 0.2) + + reorderingItemContainerView.frame = itemView.convert(itemView.bounds, to: self) + self.initialReorderingItemFrame = reorderingItemContainerView.frame + if let componentView = itemView.componentView { + reorderingItemContainerView.addSubview(componentView) + } + + self.reorderingHapticFeedback.impact() + + if self.currentReorderingScrollDisplayLink == nil { + self.currentReorderingScrollDisplayLink = ConstantDisplayLinkAnimator(update: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateReorderingAutoscroll() + }) + self.currentReorderingScrollDisplayLink?.isPaused = false + } + } + + private func endReordering() { + if let currentReorderingItemView = self.currentReorderingItemView { + self.currentReorderingItemView = nil + + if let componentView = currentReorderingItemView.componentView { + let localFrame = componentView.convert(componentView.bounds, to: self.scrollView) + currentReorderingItemView.superview?.bringSubviewToFront(currentReorderingItemView) + currentReorderingItemView.addSubview(componentView) + + let deltaPosition = CGPoint(x: localFrame.minX - currentReorderingItemView.frame.minX, y: localFrame.minY - currentReorderingItemView.frame.minY) + currentReorderingItemView.layer.animatePosition(from: deltaPosition, to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + } + } + + if let reorderingItemContainerView = self.currentReorderingItemContainerView { + self.currentReorderingItemContainerView = nil + reorderingItemContainerView.removeFromSuperview() + } + + if let currentReorderingScrollDisplayLink = self.currentReorderingScrollDisplayLink { + self.currentReorderingScrollDisplayLink = nil + currentReorderingScrollDisplayLink.invalidate() + } + + self.currentReorderingItemId = nil + self.temporaryReorderingOrderIndex = nil + + self.component?.reorderItems(self.items) + //self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + + private func updateReordering(offset: CGFloat) { + guard let itemLayout = self.itemLayout, let currentReorderingItemId = self.currentReorderingItemId, let reorderingItemContainerView = self.currentReorderingItemContainerView, let initialReorderingItemFrame = self.initialReorderingItemFrame else { + return + } + reorderingItemContainerView.frame = initialReorderingItemFrame.offsetBy(dx: offset, dy: 0.0) + + let localReorderingItemFrame = reorderingItemContainerView.convert(reorderingItemContainerView.bounds, to: self.scrollView) + + for i in 0 ..< self.items.count { + if !self.items[i].isReorderable { + continue + } + let containerFrame = itemLayout.containerFrame(at: i) + if containerFrame.intersects(localReorderingItemFrame) { + let temporaryReorderingOrderIndex: (id: AnyHashable, index: Int) = (currentReorderingItemId, i) + let hadPrevous = self.temporaryReorderingOrderIndex != nil + if self.temporaryReorderingOrderIndex?.id != temporaryReorderingOrderIndex.id || self.temporaryReorderingOrderIndex?.index != temporaryReorderingOrderIndex.index { + self.temporaryReorderingOrderIndex = temporaryReorderingOrderIndex + + if hadPrevous { + self.reorderingHapticFeedback.tap() + } + + self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + break + } + } + } + + private func updateReorderingAutoscroll() { + guard let reorderingItemContainerView = self.currentReorderingItemContainerView, let initialReorderingItemFrame = self.initialReorderingItemFrame else { + return + } + + var bounds = self.scrollView.bounds + let delta: CGFloat = 3.0 + if reorderingItemContainerView.frame.minX < 16.0 { + bounds.origin.x -= delta + } else if reorderingItemContainerView.frame.maxX > self.scrollView.bounds.width - 16.0 { + bounds.origin.x += delta + } + + if bounds.origin.x + bounds.size.width > self.scrollView.contentSize.width { + bounds.origin.x = self.scrollView.contentSize.width - bounds.size.width + } + if bounds.origin.x < 0.0 { + bounds.origin.x = 0.0 + } + + if self.scrollView.bounds != bounds { + self.scrollView.bounds = bounds + + let offset = reorderingItemContainerView.frame.minX - initialReorderingItemFrame.minX + self.updateReordering(offset: offset) + } + } + + private func updateVisibleItems(attemptSynchronousLoads: Bool, transition: Transition) { + guard let itemLayout = self.itemLayout else { + return + } + + var visibleBounds = self.scrollView.bounds + visibleBounds.origin.x -= 280.0 + visibleBounds.size.width += 560.0 + + let scale = max(0.01, self.visibilityFraction) + + var validIds = Set() + let visibleItemRange = itemLayout.visibleItemRange(for: visibleBounds) + if !self.items.isEmpty && visibleItemRange.maxIndex >= visibleItemRange.minIndex { + for index in visibleItemRange.minIndex ... visibleItemRange.maxIndex { + let item = self.items[index] + validIds.insert(item.id) + + var itemTransition = transition + let itemView: ComponentHostView + if let current = self.itemViews[item.id] { + itemView = current + } else { + itemTransition = .immediate + itemView = ComponentHostView() + self.scrollView.addSubview(itemView) + self.itemViews[item.id] = itemView + } + + let itemOuterFrame = itemLayout.contentFrame(at: index) + let itemSize = itemView.update( + transition: itemTransition, + component: item.content, + environment: { + EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded, isHighlighted: self.activeContentItemId == item.id, highlightedSubgroupId: self.activeContentItemId == item.id ? self.activeSubcontentItemId : nil) + }, + containerSize: itemOuterFrame.size + ) + let itemFrame = CGRect(origin: CGPoint(x: itemOuterFrame.minX + floor((itemOuterFrame.width - itemSize.width) / 2.0), y: itemOuterFrame.minY + floor((itemOuterFrame.height - itemSize.height) / 2.0)), size: itemSize) + itemTransition.setFrame(view: itemView, frame: itemFrame) + + transition.setSublayerTransform(view: itemView, transform: CATransform3DMakeScale(scale, scale, 1.0)) + transition.setAlpha(view: itemView, alpha: self.visibilityFraction) + } + } + var removedIds: [AnyHashable] = [] + for (id, itemView) in self.itemViews { + if !validIds.contains(id) { + removedIds.append(id) + itemView.removeFromSuperview() + } + } + for id in removedIds { + self.itemViews.removeValue(forKey: id) + } + } + + func update(component: EntityKeyboardTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + if self.component?.theme !== component.theme { + self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor + } + self.component = component + self.state = state + + if let forceActiveItemId = component.forceActiveItemId { + self.activeContentItemId = forceActiveItemId + } else if self.activeContentItemId == nil, let defaultActiveItemId = component.defaultActiveItemId { + self.activeContentItemId = defaultActiveItemId + } + + let panelEnvironment = environment[EntityKeyboardTopContainerPanelEnvironment.self].value + self.environment = panelEnvironment + + let isExpanded = availableSize.height > 34.0 + let wasExpanded = self.isExpanded + self.isExpanded = isExpanded + + if !isExpanded { + if self.isDragging { + self.isDragging = false + } + if self.isReordering { + self.isReordering = false + self.reorderGestureRecognizer?.state = .failed + } + if self.isDraggingOrReordering { + self.isDraggingOrReordering = false + } + if let draggingStoppedTimer = self.draggingStoppedTimer { + self.draggingStoppedTimer = nil + draggingStoppedTimer.invalidate() + } + } + + let intrinsicHeight: CGFloat = availableSize.height + let height = intrinsicHeight + + var items = component.items + if let (id, index) = self.temporaryReorderingOrderIndex { + for i in 0 ..< items.count { + if items[i].id == id { + let item = items.remove(at: i) + items.insert(item, at: min(index, items.count)) + break + } + } + } + self.items = items + + if self.activeContentItemId == nil { + self.activeContentItemId = items.first?.id + } + + let previousItemLayout = self.itemLayout + let itemLayout = ItemLayout(isExpanded: isExpanded, containerSideInset: component.containerSideInset, height: availableSize.height, items: self.items.map { item -> ItemLayout.ItemDescription in + let isStatic = item.id == AnyHashable("static") + return ItemLayout.ItemDescription( + isStatic: isStatic, + isStaticExpanded: isStatic && self.activeContentItemId == item.id + ) + }) + self.itemLayout = itemLayout + + self.ignoreScrolling = true + + var updatedBounds: CGRect? + if wasExpanded != isExpanded, let previousItemLayout = previousItemLayout { + if !isExpanded { + if let draggingEndOffset = self.draggingEndOffset { + if abs(self.scrollView.contentOffset.x - draggingEndOffset) > 16.0 { + self.draggingFocusItemIndex = nil + } + } else { + self.draggingFocusItemIndex = nil + } + } + + var visibleBounds = self.scrollView.bounds + visibleBounds.origin.x -= 280.0 + visibleBounds.size.width += 560.0 + + let previousVisibleRange = previousItemLayout.visibleItemRange(for: visibleBounds) + if previousVisibleRange.minIndex <= previousVisibleRange.maxIndex { + var itemIndex = self.draggingFocusItemIndex ?? ((previousVisibleRange.minIndex + previousVisibleRange.maxIndex) / 2) + if !isExpanded { + if self.scrollView.bounds.maxX >= self.scrollView.contentSize.width { + itemIndex = component.items.count - 1 + } + if self.scrollView.bounds.minX <= 0.0 { + itemIndex = 0 + } + } + + var previousItemFrame = previousItemLayout.containerFrame(at: itemIndex) + var updatedItemFrame = itemLayout.containerFrame(at: itemIndex) + + let previousDistanceToItem = (previousItemFrame.minX - self.scrollView.bounds.minX) + let previousDistanceToItemRight = (previousItemFrame.maxX - self.scrollView.bounds.maxX) + var newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.minX - previousDistanceToItem, y: 0.0), size: availableSize) + var useRightAnchor = false + if newBounds.minX > itemLayout.contentSize.width - self.scrollView.bounds.width { + newBounds.origin.x = itemLayout.contentSize.width - self.scrollView.bounds.width + itemIndex = component.items.count - 1 + useRightAnchor = true + } + if newBounds.minX < 0.0 { + newBounds.origin.x = 0.0 + itemIndex = 0 + useRightAnchor = false + } + + if useRightAnchor { + var newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.maxX - previousDistanceToItemRight, y: 0.0), size: availableSize) + if newBounds.minX > itemLayout.contentSize.width - self.scrollView.bounds.width { + newBounds.origin.x = itemLayout.contentSize.width - self.scrollView.bounds.width + } + if newBounds.minX < 0.0 { + } + } + + previousItemFrame = previousItemLayout.containerFrame(at: itemIndex) + updatedItemFrame = itemLayout.containerFrame(at: itemIndex) + + self.draggingFocusItemIndex = itemIndex + + updatedBounds = newBounds + + var updatedVisibleBounds = newBounds + updatedVisibleBounds.origin.x -= 280.0 + updatedVisibleBounds.size.width += 560.0 + let updatedVisibleRange = itemLayout.visibleItemRange(for: updatedVisibleBounds) + + if useRightAnchor { + let baseFrame = CGRect(origin: CGPoint(x: updatedItemFrame.maxX - previousItemFrame.width, y: previousItemFrame.minY), size: previousItemFrame.size) + for index in updatedVisibleRange.minIndex ... updatedVisibleRange.maxIndex { + let indexDifference = index - itemIndex + if let itemView = self.itemViews[self.items[index].id] { + let itemContainerMaxX = baseFrame.maxX + CGFloat(indexDifference) * (previousItemLayout.itemSize.width + previousItemLayout.itemSpacing) + let itemContainerFrame = CGRect(origin: CGPoint(x: itemContainerMaxX - baseFrame.width, y: baseFrame.minY), size: baseFrame.size) + let itemOuterFrame = previousItemLayout.contentFrame(index: index, containerFrame: itemContainerFrame) + + let itemSize = itemView.bounds.size + itemView.frame = CGRect(origin: CGPoint(x: itemOuterFrame.minX + floor((itemOuterFrame.width - itemSize.width) / 2.0), y: itemOuterFrame.minY + floor((itemOuterFrame.height - itemSize.height) / 2.0)), size: itemSize) + + if let activeContentItemId = self.activeContentItemId, activeContentItemId == self.items[index].id { + self.highlightedIconBackgroundView.frame = itemOuterFrame + } + } + } + } else { + let baseFrame = CGRect(origin: CGPoint(x: updatedItemFrame.minX, y: previousItemFrame.minY), size: previousItemFrame.size) + for index in updatedVisibleRange.minIndex ... updatedVisibleRange.maxIndex { + let indexDifference = index - itemIndex + if let itemView = self.itemViews[self.items[index].id] { + var itemContainerOriginX = baseFrame.minX + if indexDifference > 0 { + for i in 0 ..< indexDifference { + itemContainerOriginX += previousItemLayout.itemSpacing + itemContainerOriginX += previousItemLayout.containerFrame(at: itemIndex + i).width + } + } else if indexDifference < 0 { + for i in 0 ..< (-indexDifference) { + itemContainerOriginX -= previousItemLayout.itemSpacing + itemContainerOriginX -= previousItemLayout.containerFrame(at: itemIndex - i - 1).width + } + } + + let previousContainerFrame = previousItemLayout.containerFrame(at: index) + let itemContainerFrame = CGRect(origin: CGPoint(x: itemContainerOriginX, y: previousContainerFrame.minY), size: previousContainerFrame.size) + let itemOuterFrame = previousItemLayout.contentFrame(index: index, containerFrame: itemContainerFrame) + + let itemSize = itemView.bounds.size + itemView.frame = CGRect(origin: CGPoint(x: itemOuterFrame.minX + floor((itemOuterFrame.width - itemSize.width) / 2.0), y: itemOuterFrame.minY + floor((itemOuterFrame.height - itemSize.height) / 2.0)), size: itemSize) + + if let activeContentItemId = self.activeContentItemId, activeContentItemId == self.items[index].id { + self.highlightedIconBackgroundView.frame = itemOuterFrame + } + } + } + } + } + + if !isExpanded { + self.draggingFocusItemIndex = nil + } + } + + if self.scrollView.contentSize != itemLayout.contentSize { + self.scrollView.contentSize = itemLayout.contentSize + } + if let updatedBounds = updatedBounds { + self.scrollView.bounds = updatedBounds + } else { + self.scrollView.bounds = CGRect(origin: self.scrollView.bounds.origin, size: availableSize) + } + self.ignoreScrolling = false + + self.updateVisibleItems(attemptSynchronousLoads: !(self.scrollView.isDragging || self.scrollView.isDecelerating), transition: transition) + + if let activeContentItemId = self.activeContentItemId { + if let index = self.items.firstIndex(where: { $0.id == activeContentItemId }) { + let itemFrame = itemLayout.containerFrame(at: index) + + var highlightTransition = transition + if self.highlightedIconBackgroundView.isHidden { + self.highlightedIconBackgroundView.isHidden = false + highlightTransition = .immediate + } + + let isRound: Bool + if let string = activeContentItemId.base as? String, (string == "recent" || string == "static" || string == "trending") { + isRound = true + } else { + isRound = false + } + highlightTransition.setCornerRadius(layer: self.highlightedIconBackgroundView.layer, cornerRadius: isRound ? min(itemFrame.width / 2.0, itemFrame.height / 2.0) : 10.0) + highlightTransition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) + highlightTransition.setBounds(view: self.highlightedIconBackgroundView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + } else { + self.highlightedIconBackgroundView.isHidden = true + } + } else { + self.highlightedIconBackgroundView.isHidden = true + } + transition.setAlpha(view: self.highlightedIconBackgroundView, alpha: isExpanded ? 0.0 : 1.0) + + panelEnvironment.visibilityFractionUpdated.connect { [weak self] (fraction, transition) in + guard let strongSelf = self else { + return + } + strongSelf.visibilityFractionUpdated(value: fraction, transition: transition) + } + + component.activeContentItemIdUpdated.connect { [weak self] (itemId, subcontentItemId, transition) in + guard let strongSelf = self else { + return + } + strongSelf.activeContentItemIdUpdated(itemId: itemId, subcontentItemId: subcontentItemId, transition: transition) + } + + return CGSize(width: availableSize.width, height: height) + } + + private func visibilityFractionUpdated(value: CGFloat, transition: Transition) { + if self.visibilityFraction == value { + return + } + + self.visibilityFraction = value + + let scale = max(0.01, self.visibilityFraction) + + transition.setScale(view: self.highlightedIconBackgroundView, scale: scale) + transition.setAlpha(view: self.highlightedIconBackgroundView, alpha: self.visibilityFraction) + + for (_, itemView) in self.itemViews { + transition.setSublayerTransform(view: itemView, transform: CATransform3DMakeScale(scale, scale, 1.0)) + transition.setAlpha(view: itemView, alpha: self.visibilityFraction) + } + } + + private func activeContentItemIdUpdated(itemId: AnyHashable, subcontentItemId: AnyHashable?, transition: Transition) { + guard let component = self.component, let itemLayout = self.itemLayout else { + return + } + if self.activeContentItemId == itemId && self.activeSubcontentItemId == subcontentItemId { + return + } + self.activeContentItemId = itemId + self.activeSubcontentItemId = subcontentItemId + + let _ = component + let _ = itemLayout + self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) + + if let component = self.component, let itemLayout = self.itemLayout { + for i in 0 ..< component.items.count { + if component.items[i].id == itemId { + let itemFrame = itemLayout.containerFrame(at: i) + let expandedInset: CGFloat + if itemLayout.isExpanded { + expandedInset = -2.0 + } else { + expandedInset = -itemLayout.sideInset - (itemLayout.itemSize.width + itemLayout.itemSpacing) * 2.0 + } + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: expandedInset, dy: 0.0), animated: true) + break + } + } + } + + /*var found = false + for i in 0 ..< self.items.count { + if self.items[i].id == itemId { + found = true + self.highlightedIconBackgroundView.isHidden = false + let itemFrame = itemLayout.containerFrame(at: i) + + var highlightTransition = transition + if highlightTransition.animation.isImmediate { + highlightTransition = highlightTransition.withAnimation(.curve(duration: 0.3, curve: .spring)) + } + highlightTransition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) + highlightTransition.setBounds(view: self.highlightedIconBackgroundView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -6.0, dy: 0.0), animated: true) + + break + } + } + if !found { + self.highlightedIconBackgroundView.isHidden = true + }*/ + } + + override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if self.visibilityFraction < 0.5 { + return nil + } + return super.hitTest(point, with: event) + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift new file mode 100644 index 0000000000..6424d92c18 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift @@ -0,0 +1,122 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import AnimationCache +import MultiAnimationRenderer +import AccountContext +import AsyncDisplayKit +import ComponentDisplayAdapters + +public protocol EntitySearchContainerNode: ASDisplayNode { + var onCancel: (() -> Void)? { get set } + + func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, inputHeight: CGFloat, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition) +} + +final class EntitySearchContentEnvironment: Equatable { + let context: AccountContext + let theme: PresentationTheme + let deviceMetrics: DeviceMetrics + + init( + context: AccountContext, + theme: PresentationTheme, + deviceMetrics: DeviceMetrics + ) { + self.context = context + self.theme = theme + self.deviceMetrics = deviceMetrics + } + + static func ==(lhs: EntitySearchContentEnvironment, rhs: EntitySearchContentEnvironment) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.deviceMetrics != rhs.deviceMetrics { + return false + } + + return true + } +} + +final class EntitySearchContentComponent: Component { + typealias EnvironmentType = EntitySearchContentEnvironment + + let makeContainerNode: () -> EntitySearchContainerNode? + let dismissSearch: () -> Void + + init( + makeContainerNode: @escaping () -> EntitySearchContainerNode?, + dismissSearch: @escaping () -> Void + ) { + self.makeContainerNode = makeContainerNode + self.dismissSearch = dismissSearch + } + + static func ==(lhs: EntitySearchContentComponent, rhs: EntitySearchContentComponent) -> Bool { + return true + } + + final class View: UIView { + private var containerNode: EntitySearchContainerNode? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: EntitySearchContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let containerNode: EntitySearchContainerNode? + if let current = self.containerNode { + containerNode = current + } else { + containerNode = component.makeContainerNode() + if let containerNode = containerNode { + self.containerNode = containerNode + self.addSubnode(containerNode) + } + } + + if let containerNode = containerNode { + + let environmentValue = environment[EntitySearchContentEnvironment.self].value + transition.setFrame(view: containerNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) + containerNode.updateLayout( + size: availableSize, + leftInset: 0.0, + rightInset: 0.0, + bottomInset: 0.0, + inputHeight: 0.0, + deviceMetrics: environmentValue.deviceMetrics, + transition: transition.containedViewLayoutTransition + ) + + containerNode.onCancel = { + component.dismissSearch() + } + } + + return availableSize + } + } + + func makeView() -> View { + return View(frame: CGRect()) + } + + func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift new file mode 100644 index 0000000000..2194d5b83f --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -0,0 +1,833 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import MultiAnimationRenderer +import AnimationCache +import AccountContext +import LottieAnimationCache +import AnimatedStickerNode +import TelegramAnimatedStickerNode +import SwiftSignalKit +import ShimmerEffect +import PagerComponent +import SoftwareVideo +import AVFoundation +import PhotoResources +import ContextUI +import ShimmerEffect + +private class GifVideoLayer: AVSampleBufferDisplayLayer { + private let context: AccountContext + private let file: TelegramMediaFile? + + private var frameManager: SoftwareVideoLayerFrameManager? + + private var thumbnailDisposable: Disposable? + + private var playbackTimestamp: Double = 0.0 + private var playbackTimer: SwiftSignalKit.Timer? + + var started: (() -> Void)? + + var shouldBeAnimating: Bool = false { + didSet { + if self.shouldBeAnimating == oldValue { + return + } + + if self.shouldBeAnimating { + self.playbackTimer?.invalidate() + let startTimestamp = self.playbackTimestamp + CFAbsoluteTimeGetCurrent() + self.playbackTimer = SwiftSignalKit.Timer(timeout: 1.0 / 30.0, repeat: true, completion: { [weak self] in + guard let strongSelf = self else { + return + } + let timestamp = CFAbsoluteTimeGetCurrent() - startTimestamp + strongSelf.frameManager?.tick(timestamp: timestamp) + strongSelf.playbackTimestamp = timestamp + }, queue: .mainQueue()) + self.playbackTimer?.start() + } else { + self.playbackTimer?.invalidate() + self.playbackTimer = nil + } + } + } + + init(context: AccountContext, file: TelegramMediaFile?, synchronousLoad: Bool) { + self.context = context + self.file = file + + super.init() + + self.videoGravity = .resizeAspectFill + + if let file = self.file { + if let dimensions = file.dimensions { + self.thumbnailDisposable = (mediaGridMessageVideo(postbox: context.account.postbox, videoReference: .savedGif(media: file), synchronousLoad: synchronousLoad, nilForEmptyResult: true) + |> deliverOnMainQueue).start(next: { [weak self] transform in + guard let strongSelf = self else { + return + } + let boundingSize = CGSize(width: 93.0, height: 93.0) + let imageSize = dimensions.cgSize.aspectFilled(boundingSize) + + if let image = transform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { + Queue.mainQueue().async { + if let strongSelf = self { + strongSelf.contents = image.cgImage + strongSelf.setupVideo() + strongSelf.started?() + } + } + } else { + strongSelf.setupVideo() + } + }) + } else { + self.setupVideo() + } + } + } + + override init(layer: Any) { + preconditionFailure() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.thumbnailDisposable?.dispose() + } + + private func setupVideo() { + guard let file = self.file else { + return + } + let frameManager = SoftwareVideoLayerFrameManager(account: self.context.account, fileReference: .savedGif(media: file), layerHolder: nil, layer: self) + self.frameManager = frameManager + frameManager.started = { [weak self] in + guard let strongSelf = self else { + return + } + let _ = strongSelf + } + frameManager.start() + } +} + +public final class GifPagerContentComponent: Component { + public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) + + public enum Subject: Equatable { + case recent + case trending + case emojiSearch(String) + } + + public final class InputInteraction { + public let performItemAction: (Item, UIView, CGRect) -> Void + public let openGifContextMenu: (Item, UIView, CGRect, ContextGesture, Bool) -> Void + public let loadMore: (String) -> Void + + public init( + performItemAction: @escaping (Item, UIView, CGRect) -> Void, + openGifContextMenu: @escaping (Item, UIView, CGRect, ContextGesture, Bool) -> Void, + loadMore: @escaping (String) -> Void + ) { + self.performItemAction = performItemAction + self.openGifContextMenu = openGifContextMenu + self.loadMore = loadMore + } + } + + public final class Item: Equatable { + public let file: FileMediaReference + public let contextResult: (ChatContextResultCollection, ChatContextResult)? + + public init(file: FileMediaReference, contextResult: (ChatContextResultCollection, ChatContextResult)?) { + self.file = file + self.contextResult = contextResult + } + + public static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs === rhs { + return true + } + if lhs.file.media.fileId != rhs.file.media.fileId { + return false + } + if (lhs.contextResult == nil) != (rhs.contextResult != nil) { + return false + } + + return true + } + } + + public let context: AccountContext + public let inputInteraction: InputInteraction + public let subject: Subject + public let items: [Item] + public let isLoading: Bool + public let loadMoreToken: String? + + public init( + context: AccountContext, + inputInteraction: InputInteraction, + subject: Subject, + items: [Item], + isLoading: Bool, + loadMoreToken: String? + ) { + self.context = context + self.inputInteraction = inputInteraction + self.subject = subject + self.items = items + self.isLoading = isLoading + self.loadMoreToken = loadMoreToken + } + + public static func ==(lhs: GifPagerContentComponent, rhs: GifPagerContentComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.inputInteraction !== rhs.inputInteraction { + return false + } + if lhs.subject != rhs.subject { + return false + } + if lhs.items != rhs.items { + return false + } + if lhs.isLoading != rhs.isLoading { + return false + } + if lhs.loadMoreToken != rhs.loadMoreToken { + return false + } + + return true + } + + public final class View: ContextControllerSourceView, PagerContentViewWithBackground, UIScrollViewDelegate { + private struct ItemGroupDescription: Equatable { + let hasTitle: Bool + let itemCount: Int + } + + private struct ItemGroupLayout: Equatable { + let frame: CGRect + let itemTopOffset: CGFloat + let itemCount: Int + } + + private struct ItemLayout: Equatable { + let width: CGFloat + let containerInsets: UIEdgeInsets + let itemCount: Int + let itemSize: CGFloat + let horizontalSpacing: CGFloat + let verticalSpacing: CGFloat + let itemsPerRow: Int + let contentSize: CGSize + + init(width: CGFloat, containerInsets: UIEdgeInsets, itemCount: Int) { + self.width = width + self.containerInsets = containerInsets + self.itemCount = itemCount + self.horizontalSpacing = 1.0 + self.verticalSpacing = 1.0 + + let defaultItemSize: CGFloat = 120.0 + + let itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right + var itemsPerRow = Int(floor((itemHorizontalSpace) / (defaultItemSize))) + itemsPerRow = max(3, itemsPerRow) + + self.itemsPerRow = itemsPerRow + + self.itemSize = floor((itemHorizontalSpace - self.horizontalSpacing * CGFloat(itemsPerRow - 1)) / CGFloat(itemsPerRow)) + + let numRowsInGroup = (itemCount + (self.itemsPerRow - 1)) / self.itemsPerRow + self.contentSize = CGSize(width: width, height: self.containerInsets.top + self.containerInsets.bottom + CGFloat(numRowsInGroup) * self.itemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + } + + func frame(at index: Int) -> CGRect { + let row = index / self.itemsPerRow + let column = index % self.itemsPerRow + + var rect = CGRect( + origin: CGPoint( + x: self.containerInsets.left + CGFloat(column) * (self.itemSize + self.horizontalSpacing), + y: self.containerInsets.top + CGFloat(row) * (self.itemSize + self.verticalSpacing) + ), + size: CGSize( + width: self.itemSize, + height: self.itemSize + ) + ) + + if column == self.itemsPerRow - 1 && index < self.itemCount - 1 { + rect.size.width = self.width - self.containerInsets.right - rect.minX + } + + return rect + } + + func visibleItems(for rect: CGRect) -> Range? { + let offsetRect = rect.offsetBy(dx: -self.containerInsets.left, dy: -containerInsets.top) + var minVisibleRow = Int(floor((offsetRect.minY - self.verticalSpacing) / (self.itemSize + self.verticalSpacing))) + minVisibleRow = max(0, minVisibleRow) + let maxVisibleRow = Int(ceil((offsetRect.maxY - self.verticalSpacing) / (self.itemSize + self.verticalSpacing))) + + let minVisibleIndex = minVisibleRow * self.itemsPerRow + let maxVisibleIndex = (maxVisibleRow + 1) * self.itemsPerRow - 1 + + if maxVisibleIndex >= minVisibleIndex { + return minVisibleIndex ..< (maxVisibleIndex + 1) + } else { + return nil + } + } + } + + fileprivate enum ItemKey: Hashable { + case media(MediaId) + case placeholder(Int) + } + + fileprivate final class ItemLayer: GifVideoLayer { + let item: Item? + + private var disposable: Disposable? + private var fetchDisposable: Disposable? + + private var isInHierarchyValue: Bool = false + public var isVisibleForAnimations: Bool = false { + didSet { + if self.isVisibleForAnimations != oldValue { + self.updatePlayback() + } + } + } + private(set) var displayPlaceholder: Bool = false + let onUpdateDisplayPlaceholder: (Bool, Double) -> Void + + init( + item: Item?, + context: AccountContext, + groupId: String, + attemptSynchronousLoad: Bool, + onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void + ) { + self.item = item + self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder + + super.init(context: context, file: item?.file.media, synchronousLoad: attemptSynchronousLoad) + + if item == nil { + self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0) + } + + self.started = { [weak self] in + let _ = self + //self?.updateDisplayPlaceholder(displayPlaceholder: false, duration: 0.2) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.disposable?.dispose() + self.fetchDisposable?.dispose() + } + + override func action(forKey event: String) -> CAAction? { + if event == kCAOnOrderIn { + self.isInHierarchyValue = true + } else if event == kCAOnOrderOut { + self.isInHierarchyValue = false + } + self.updatePlayback() + return nullAction + } + + private func updatePlayback() { + let shouldBePlaying = self.isInHierarchyValue && self.isVisibleForAnimations + + self.shouldBeAnimating = shouldBePlaying + } + + func updateDisplayPlaceholder(displayPlaceholder: Bool, duration: Double) { + if self.displayPlaceholder == displayPlaceholder { + return + } + self.displayPlaceholder = displayPlaceholder + self.onUpdateDisplayPlaceholder(displayPlaceholder, duration) + } + } + + final class ItemPlaceholderView: UIView { + private let shimmerView: PortalSourceView? + private var placeholderView: PortalView? + + init(shimmerView: PortalSourceView?) { + self.shimmerView = shimmerView + self.placeholderView = PortalView() + + super.init(frame: CGRect()) + + self.clipsToBounds = true + + if let placeholderView = self.placeholderView, let shimmerView = self.shimmerView { + placeholderView.view.clipsToBounds = true + self.addSubview(placeholderView.view) + shimmerView.addPortal(view: placeholderView) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(size: CGSize) { + if let placeholderView = self.placeholderView { + placeholderView.view.frame = CGRect(origin: CGPoint(), size: size) + } + } + } + + private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { + } + + private let backgroundView: BlurredBackgroundView + + private let shimmerHostView: PortalSourceView + private let standaloneShimmerEffect: StandaloneShimmerEffect + + private let scrollView: ContentScrollView + + private let placeholdersContainerView: UIView + private var visibleItemPlaceholderViews: [ItemKey: ItemPlaceholderView] = [:] + private var visibleItemLayers: [ItemKey: ItemLayer] = [:] + private var ignoreScrolling: Bool = false + + private var component: GifPagerContentComponent? + private var pagerEnvironment: PagerComponentChildEnvironment? + private var theme: PresentationTheme? + private var itemLayout: ItemLayout? + + private var currentLoadMoreToken: String? + + override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: nil) + + self.shimmerHostView = PortalSourceView() + self.standaloneShimmerEffect = StandaloneShimmerEffect() + + self.placeholdersContainerView = UIView() + + self.scrollView = ContentScrollView() + + super.init(frame: frame) + + self.addSubview(self.backgroundView) + + self.shimmerHostView.alpha = 0.0 + self.addSubview(self.shimmerHostView) + + self.scrollView.delaysContentTouches = false + if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { + self.scrollView.contentInsetAdjustmentBehavior = .never + } + if #available(iOS 13.0, *) { + self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + self.scrollView.showsVerticalScrollIndicator = true + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.scrollsToTop = false + self.scrollView.delegate = self + self.addSubview(self.scrollView) + + self.scrollView.addSubview(self.placeholdersContainerView) + + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + + self.isMultipleTouchEnabled = false + + self.useSublayerTransformForActivation = false + self.shouldBegin = { [weak self] point in + guard let strongSelf = self else { + return false + } + strongSelf.targetLayerForActivationProgress = nil + if let (_, itemLayer) = strongSelf.itemLayer(atPoint: point) { + strongSelf.targetLayerForActivationProgress = itemLayer + return true + } + return false + } + self.activated = { [weak self] gesture, location in + guard let strongSelf = self, let component = strongSelf.component else { + gesture.cancel() + return + } + guard let (item, itemLayer) = strongSelf.itemLayer(atPoint: location) else { + gesture.cancel() + return + } + let rect = strongSelf.scrollView.convert(itemLayer.frame, to: strongSelf) + component.inputInteraction.openGifContextMenu(item, strongSelf, rect, gesture, component.subject == .recent) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func openGifContextMenu(item: Item, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + guard let component = self.component else { + return + } + component.inputInteraction.openGifContextMenu(item, sourceView, sourceRect, gesture, isSaved) + } + + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + if case .ended = recognizer.state { + if let component = self.component, let item = self.item(atPoint: recognizer.location(in: self)), let itemView = self.visibleItemLayers[.media(item.file.media.fileId)] { + component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemView.frame, to: self)) + } + } + } + + private func item(atPoint point: CGPoint) -> Item? { + let localPoint = self.convert(point, to: self.scrollView) + + for (_, itemLayer) in self.visibleItemLayers { + if itemLayer.frame.contains(localPoint) { + return itemLayer.item + } + } + + return nil + } + + private func itemLayer(atPoint point: CGPoint) -> (Item, ItemLayer)? { + let localPoint = self.convert(point, to: self.scrollView) + + for (_, itemLayer) in self.visibleItemLayers { + if itemLayer.frame.contains(localPoint) { + if let item = itemLayer.item { + return (item, itemLayer) + } else { + return nil + } + } + } + + return nil + } + + private var previousScrollingOffset: CGFloat? + + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + if let presentation = scrollView.layer.presentation() { + scrollView.bounds = presentation.bounds + scrollView.layer.removeAllAnimations() + } + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + + self.updateVisibleItems(attemptSynchronousLoads: false) + + self.updateScrollingOffset(transition: .immediate) + + if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.height - 100.0 { + if let component = self.component, let loadMoreToken = component.loadMoreToken, self.currentLoadMoreToken != loadMoreToken { + self.currentLoadMoreToken = loadMoreToken + component.inputInteraction.loadMore(loadMoreToken) + } + } + } + + public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + if velocity.y != 0.0 { + targetContentOffset.pointee.y = self.snappedContentOffset(proposedOffset: targetContentOffset.pointee.y) + } + } + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if !decelerate { + self.snapScrollingOffsetToInsets() + } + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + self.snapScrollingOffsetToInsets() + } + + private func updateScrollingOffset(transition: Transition) { + let isInteracting = scrollView.isDragging || scrollView.isDecelerating + if let previousScrollingOffsetValue = self.previousScrollingOffset { + let currentBounds = scrollView.bounds + let offsetToTopEdge = max(0.0, currentBounds.minY - 0.0) + let offsetToBottomEdge = max(0.0, scrollView.contentSize.height - currentBounds.maxY) + + let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue + self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( + relativeOffset: relativeOffset, + absoluteOffsetToTopEdge: offsetToTopEdge, + absoluteOffsetToBottomEdge: offsetToBottomEdge, + isReset: false, + isInteracting: isInteracting, + transition: transition + )) + self.previousScrollingOffset = scrollView.contentOffset.y + } + self.previousScrollingOffset = scrollView.contentOffset.y + } + + private func snappedContentOffset(proposedOffset: CGFloat) -> CGFloat { + guard let pagerEnvironment = self.pagerEnvironment else { + return proposedOffset + } + + var proposedOffset = proposedOffset + let bounds = self.bounds + if proposedOffset + bounds.height > self.scrollView.contentSize.height - pagerEnvironment.containerInsets.bottom { + proposedOffset = self.scrollView.contentSize.height - bounds.height + } + if proposedOffset < pagerEnvironment.containerInsets.top { + proposedOffset = 0.0 + } + + return proposedOffset + } + + private func snapScrollingOffsetToInsets() { + let transition = Transition(animation: .curve(duration: 0.4, curve: .spring)) + + var currentBounds = self.scrollView.bounds + currentBounds.origin.y = self.snappedContentOffset(proposedOffset: currentBounds.minY) + transition.setBounds(view: self.scrollView, bounds: currentBounds) + + self.updateScrollingOffset(transition: transition) + } + + private func updateVisibleItems(attemptSynchronousLoads: Bool) { + guard let component = self.component, let itemLayout = self.itemLayout else { + return + } + + var validIds = Set() + + if let itemRange = itemLayout.visibleItems(for: self.scrollView.bounds) { + for index in itemRange.lowerBound ..< itemRange.upperBound { + var item: Item? + let itemId: ItemKey + if index < component.items.count { + item = component.items[index] + itemId = .media(component.items[index].file.media.fileId) + } else if component.isLoading || component.loadMoreToken != nil { + itemId = .placeholder(index) + } else { + continue + } + + if !component.isLoading { + if let placeholderView = self.visibleItemPlaceholderViews.removeValue(forKey: .placeholder(index)) { + self.visibleItemPlaceholderViews[itemId] = placeholderView + } + } + + validIds.insert(itemId) + + let itemFrame = itemLayout.frame(at: index) + + let itemTransition: Transition = .immediate + var updateItemLayerPlaceholder = false + + let itemLayer: ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + updateItemLayerPlaceholder = true + + itemLayer = ItemLayer( + item: item, + context: component.context, + groupId: "savedGif", + attemptSynchronousLoad: attemptSynchronousLoads, + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in + guard let strongSelf = self else { + return + } + if displayPlaceholder { + if let itemLayer = strongSelf.visibleItemLayers[itemId] { + let placeholderView: ItemPlaceholderView + if let current = strongSelf.visibleItemPlaceholderViews[itemId] { + placeholderView = current + } else { + placeholderView = ItemPlaceholderView(shimmerView: strongSelf.shimmerHostView) + strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView + strongSelf.placeholdersContainerView.addSubview(placeholderView) + } + placeholderView.frame = itemLayer.frame + placeholderView.update(size: placeholderView.bounds.size) + + strongSelf.updateShimmerIfNeeded() + } + } else { + if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { + strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) + if duration > 0.0 { + if let itemLayer = strongSelf.visibleItemLayers[itemId] { + itemLayer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) + } + + placeholderView.alpha = 0.0 + placeholderView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, completion: { [weak self, weak placeholderView] _ in + placeholderView?.removeFromSuperview() + self?.updateShimmerIfNeeded() + }) + } else { + placeholderView.removeFromSuperview() + strongSelf.updateShimmerIfNeeded() + } + } + } + } + ) + self.scrollView.layer.addSublayer(itemLayer) + self.visibleItemLayers[itemId] = itemLayer + } + + let itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) + + itemTransition.setFrame(layer: itemLayer, frame: itemFrame) + itemLayer.isVisibleForAnimations = true + + if let placeholderView = self.visibleItemPlaceholderViews[itemId] { + if placeholderView.layer.position != itemPosition || placeholderView.layer.bounds != itemBounds { + itemTransition.setFrame(view: placeholderView, frame: itemFrame) + placeholderView.update(size: itemFrame.size) + } + } + + if updateItemLayerPlaceholder { + if itemLayer.displayPlaceholder { + itemLayer.onUpdateDisplayPlaceholder(true, 0.0) + } else { + itemLayer.onUpdateDisplayPlaceholder(false, 0.2) + } + } + } + } + + var removedIds: [ItemKey] = [] + for (id, itemLayer) in self.visibleItemLayers { + if !validIds.contains(id) { + removedIds.append(id) + itemLayer.removeFromSuperlayer() + + if let view = self.visibleItemPlaceholderViews.removeValue(forKey: id) { + view.removeFromSuperview() + } + } + } + for id in removedIds { + self.visibleItemLayers.removeValue(forKey: id) + } + } + + private func updateShimmerIfNeeded() { + if self.placeholdersContainerView.subviews.isEmpty { + self.standaloneShimmerEffect.layer = nil + } else { + self.standaloneShimmerEffect.layer = self.shimmerHostView.layer + } + } + + public func pagerUpdateBackground(backgroundFrame: CGRect, transition: Transition) { + guard let theme = self.theme else { + return + } + self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.backgroundColor, enableBlur: true, forceKeepBlur: false, transition: transition.containedViewLayoutTransition) + transition.setFrame(view: self.backgroundView, frame: backgroundFrame) + self.backgroundView.update(size: backgroundFrame.size, transition: transition.containedViewLayoutTransition) + } + + func update(component: GifPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + var contentReset = false + if let previousComponent = self.component, previousComponent.subject != component.subject { + contentReset = true + self.currentLoadMoreToken = nil + } + + let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value + + self.component = component + self.theme = keyboardChildEnvironment.theme + + let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value + self.pagerEnvironment = pagerEnvironment + + transition.setFrame(view: self.shimmerHostView, frame: CGRect(origin: CGPoint(), size: availableSize)) + + let shimmerBackgroundColor = keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08) + let shimmerForegroundColor = keyboardChildEnvironment.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) + self.standaloneShimmerEffect.update(background: shimmerBackgroundColor, foreground: shimmerForegroundColor) + + let itemLayout = ItemLayout( + width: availableSize.width, + containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top, left: pagerEnvironment.containerInsets.left, bottom: pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right), + itemCount: component.items.count + ) + self.itemLayout = itemLayout + + self.ignoreScrolling = true + transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: availableSize)) + if self.scrollView.contentSize != itemLayout.contentSize { + self.scrollView.contentSize = itemLayout.contentSize + } + if self.scrollView.scrollIndicatorInsets != pagerEnvironment.containerInsets { + self.scrollView.scrollIndicatorInsets = pagerEnvironment.containerInsets + } + + if contentReset { + self.scrollView.setContentOffset(CGPoint(), animated: false) + } + + self.previousScrollingOffset = self.scrollView.contentOffset.y + self.ignoreScrolling = false + + self.updateVisibleItems(attemptSynchronousLoads: true) + + return availableSize + } + } + + public func makeView() -> View { + return View(frame: CGRect()) + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) + } +} diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/BUILD b/submodules/TelegramUI/Components/LottieAnimationCache/BUILD index 434120005d..15079a8090 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/BUILD +++ b/submodules/TelegramUI/Components/LottieAnimationCache/BUILD @@ -15,6 +15,7 @@ swift_library( "//submodules/Display:Display", "//submodules/rlottie:RLottieBinding", "//submodules/GZip:GZip", + "//submodules/WebPBinding:WebPBinding", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index 1049ce1d21..7856c916f0 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -4,20 +4,58 @@ import AnimationCache import Display import RLottieBinding import GZip +import WebPBinding public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: AnimationCacheItemWriter) { - let decompressedData = TGGUnzipData(data, 512 * 1024) ?? data - guard let animation = LottieInstance(data: decompressedData, fitzModifier: .none, colorReplacements: nil, cacheKey: "") else { + writer.queue.async { + let decompressedData = TGGUnzipData(data, 1 * 1024 * 1024) ?? data + guard let animation = LottieInstance(data: decompressedData, fitzModifier: .none, colorReplacements: nil, cacheKey: "") else { + writer.finish() + return + } + + + let frameSkip: Int + if animation.frameRate >= 60 { + if ProcessInfo.processInfo.processorCount > 2 { + frameSkip = 1 + } else { + frameSkip = 2 + } + } else { + frameSkip = 1 + } + + let frameDuration = Double(frameSkip) / Double(animation.frameRate) + for i in stride(from: 0, through: animation.frameCount - 1, by: frameSkip) { + if writer.isCancelled { + break + } + writer.add(with: { surface in + animation.renderFrame(with: i, into: surface.argb, width: Int32(surface.width), height: Int32(surface.height), bytesPerRow: Int32(surface.bytesPerRow)) + return frameDuration + }, proposedWidth: width, proposedHeight: height) + } + + writer.finish() + } +} + +public func cacheStillSticker(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter) { + writer.queue.async { + if let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let image = WebP.convert(fromWebP: data) { + writer.add(with: { surface in + let context = DrawingContext(size: CGSize(width: CGFloat(surface.width), height: CGFloat(surface.height)), scale: 1.0, opaque: false, clear: true, bytesPerRow: surface.bytesPerRow) + context.withFlippedContext { c in + UIGraphicsPushContext(c) + c.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: context.size)) + UIGraphicsPopContext() + } + memcpy(surface.argb, context.bytes, surface.height * surface.bytesPerRow) + return 1.0 + }, proposedWidth: width, proposedHeight: height) + } + writer.finish() - return } - let size = CGSize(width: width, height: height) - let context = DrawingContext(size: size, scale: 1.0, opaque: false, clear: true) - let frameDuration = 1.0 / Double(animation.frameRate) - for i in 0 ..< animation.frameCount { - animation.renderFrame(with: i, into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(context.scaledSize.width), height: Int32(context.scaledSize.height), bytesPerRow: Int32(context.bytesPerRow)) - writer.add(bytes: context.bytes, length: context.length, width: Int(context.scaledSize.width), height: Int(context.scaledSize.height), bytesPerRow: Int(context.bytesPerRow), duration: frameDuration) - } - - writer.finish() } diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/BUILD b/submodules/TelegramUI/Components/MultiAnimationRenderer/BUILD index e5a853e167..4f5a66267d 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/BUILD +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/BUILD @@ -1,4 +1,44 @@ load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") +load( + "@build_bazel_rules_apple//apple:resources.bzl", + "apple_resource_bundle", + "apple_resource_group", +) +load("//build-system/bazel-utils:plist_fragment.bzl", + "plist_fragment", +) + +filegroup( + name = "MultiAnimationRendererMetalResources", + srcs = glob([ + "Resources/**/*.metal", + ]), + visibility = ["//visibility:public"], +) + +plist_fragment( + name = "WallpaperBackgroundNodeBundleInfoPlist", + extension = "plist", + template = + """ + CFBundleIdentifier + org.telegram.MultiAnimationRenderer + CFBundleDevelopmentRegion + en + CFBundleName + MultiAnimationRenderer + """ +) + +apple_resource_bundle( + name = "MultiAnimationRendererBundle", + infoplists = [ + ":WallpaperBackgroundNodeBundleInfoPlist", + ], + resources = [ + ":MultiAnimationRendererMetalResources", + ], +) swift_library( name = "MultiAnimationRenderer", @@ -6,6 +46,9 @@ swift_library( srcs = glob([ "Sources/**/*.swift", ]), + data = [ + ":MultiAnimationRendererBundle", + ], copts = [ "-warnings-as-errors", ], diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal new file mode 100644 index 0000000000..8343f753f0 --- /dev/null +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal @@ -0,0 +1,46 @@ +#include +using namespace metal; + +typedef struct { + packed_float2 position; + packed_float2 texCoord; +} Vertex; + +typedef struct { + float4 position[[position]]; + float2 texCoord; +} Varyings; + +vertex Varyings multiAnimationVertex( + unsigned int vid[[vertex_id]], + constant Vertex *verticies[[buffer(0)]], + constant uint2 &resolution[[buffer(1)]], + constant uint2 &slotSize[[buffer(2)]], + constant uint2 &slotPosition[[buffer(3)]] +) { + Varyings out; + constant Vertex &v = verticies[vid]; + + out.position = float4(float2(v.position), 0.0, 1.0); + out.texCoord = v.texCoord; + + return out; +} + +fragment half4 multiAnimationFragment( + Varyings in[[stage_in]], + texture2d textureY[[texture(0)]], + texture2d textureU[[texture(1)]], + texture2d textureV[[texture(2)]], + texture2d textureA[[texture(3)]] +) { + constexpr sampler s(address::clamp_to_edge, filter::linear); + + half y = textureY.sample(s, in.texCoord).r; + half u = textureU.sample(s, in.texCoord).r - 0.5; + half v = textureV.sample(s, in.texCoord).r - 0.5; + half a = textureA.sample(s, in.texCoord).r; + + half4 out = half4(1.5748 * v + y, -0.1873 * v + y, 1.8556 * u + y, a); + return half4(out.b, out.g, out.r, out.a); +} diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift new file mode 100644 index 0000000000..00f1837d90 --- /dev/null +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -0,0 +1,883 @@ +import Foundation +import UIKit +import SwiftSignalKit +import Display +import AnimationCache +import Accelerate +import simd + +private func alignUp(size: Int, align: Int) -> Int { + precondition(((align - 1) & align) == 0, "Align must be a power of two") + + let alignmentMask = align - 1 + return (size + alignmentMask) & ~alignmentMask +} + +private extension Float { + func remap(fromLow: Float, fromHigh: Float, toLow: Float, toHigh: Float) -> Float { + guard (fromHigh - fromLow) != 0.0 else { + return 0.0 + } + return toLow + (self - fromLow) * (toHigh - toLow) / (fromHigh - fromLow) + } +} + +private func makePipelineState(device: MTLDevice, library: MTLLibrary, vertexProgram: String, fragmentProgram: String) -> MTLRenderPipelineState? { + guard let loadedVertexProgram = library.makeFunction(name: vertexProgram) else { + return nil + } + guard let loadedFragmentProgram = library.makeFunction(name: fragmentProgram) else { + return nil + } + + let pipelineStateDescriptor = MTLRenderPipelineDescriptor() + pipelineStateDescriptor.vertexFunction = loadedVertexProgram + pipelineStateDescriptor.fragmentFunction = loadedFragmentProgram + pipelineStateDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm + guard let pipelineState = try? device.makeRenderPipelineState(descriptor: pipelineStateDescriptor) else { + return nil + } + + return pipelineState +} + +@available(iOS 13.0, *) +public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { + private final class LoadFrameTask { + let task: () -> () -> Void + + init(task: @escaping () -> () -> Void) { + self.task = task + } + } + + private final class TargetReference { + let id: Int64 + weak var value: MultiAnimationRenderTarget? + + init(_ value: MultiAnimationRenderTarget) { + self.value = value + self.id = value.id + } + } + + private final class TextureStoragePool { + struct Parameters { + let width: Int + let height: Int + let format: TextureStorage.Content.Format + } + + let parameters: Parameters + private var items: [TextureStorage.Content] = [] + private var cleanupTimer: Foundation.Timer? + private var lastTakeTimestamp: Double = 0.0 + + init(width: Int, height: Int, format: TextureStorage.Content.Format) { + self.parameters = Parameters(width: width, height: height, format: format) + + let cleanupTimer = Foundation.Timer(timeInterval: 2.0, repeats: true, block: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.collect() + }) + self.cleanupTimer = cleanupTimer + RunLoop.main.add(cleanupTimer, forMode: .common) + } + + deinit { + self.cleanupTimer?.invalidate() + } + + private func collect() { + let timestamp = CFAbsoluteTimeGetCurrent() + if timestamp - self.lastTakeTimestamp < 1.0 { + return + } + if self.items.count > 32 { + autoreleasepool { + var remainingItems: [Unmanaged] = [] + while self.items.count > 32 { + let item = self.items.removeLast() + remainingItems.append(Unmanaged.passRetained(item)) + } + DispatchQueue.global().async { + autoreleasepool { + for item in remainingItems { + item.release() + } + } + } + } + } + } + + func recycle(content: TextureStorage.Content) { + self.items.append(content) + } + + func take() -> TextureStorage? { + if self.items.isEmpty { + self.lastTakeTimestamp = CFAbsoluteTimeGetCurrent() + return nil + } + return TextureStorage(pool: self, content: self.items.removeLast()) + } + + static func takeNew(device: MTLDevice, parameters: Parameters, pool: TextureStoragePool) -> TextureStorage? { + guard let content = TextureStorage.Content(device: device, width: parameters.width, height: parameters.height, format: parameters.format) else { + return nil + } + return TextureStorage(pool: pool, content: content) + } + } + + private final class TextureStorage { + final class Content { + enum Format { + case bgra + case r + } + + let buffer: MTLBuffer? + + let width: Int + let height: Int + let bytesPerRow: Int + let texture: MTLTexture + + static func rowAlignment(device: MTLDevice, format: Format) -> Int { + let pixelFormat: MTLPixelFormat + switch format { + case .bgra: + pixelFormat = .bgra8Unorm + case .r: + pixelFormat = .r8Unorm + } + return device.minimumLinearTextureAlignment(for: pixelFormat) + } + + init?(device: MTLDevice, width: Int, height: Int, format: Format) { + let bytesPerPixel: Int + let pixelFormat: MTLPixelFormat + switch format { + case .bgra: + bytesPerPixel = 4 + pixelFormat = .bgra8Unorm + case .r: + bytesPerPixel = 1 + pixelFormat = .r8Unorm + } + let pixelRowAlignment = Content.rowAlignment(device: device, format: format) + let bytesPerRow = alignUp(size: width * bytesPerPixel, align: pixelRowAlignment) + + self.width = width + self.height = height + self.bytesPerRow = bytesPerRow + + #if targetEnvironment(simulator) + let textureDescriptor = MTLTextureDescriptor() + textureDescriptor.textureType = .type2D + textureDescriptor.pixelFormat = pixelFormat + textureDescriptor.width = width + textureDescriptor.height = height + textureDescriptor.usage = [.shaderRead] + textureDescriptor.storageMode = .shared + + guard let texture = device.makeTexture(descriptor: textureDescriptor) else { + return nil + } + self.buffer = nil + #else + guard let buffer = device.makeBuffer(length: bytesPerRow * height, options: MTLResourceOptions.storageModeShared) else { + return nil + } + self.buffer = buffer + + let textureDescriptor = MTLTextureDescriptor() + textureDescriptor.textureType = .type2D + textureDescriptor.pixelFormat = pixelFormat + textureDescriptor.width = width + textureDescriptor.height = height + textureDescriptor.usage = [.shaderRead] + textureDescriptor.storageMode = buffer.storageMode + + guard let texture = buffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: bytesPerRow) else { + return nil + } + #endif + + self.texture = texture + } + + func replace(rgbaData: Data, width: Int, height: Int, bytesPerRow: Int) { + if width != self.width || height != self.height { + assert(false, "Image size does not match") + return + } + let region = MTLRegion(origin: MTLOrigin(x: 0, y: 0, z: 0), size: MTLSize(width: width, height: height, depth: 1)) + + if let buffer = self.buffer, self.bytesPerRow == bytesPerRow { + assert(bytesPerRow * height <= rgbaData.count) + + rgbaData.withUnsafeBytes { bytes in + let _ = memcpy(buffer.contents(), bytes.baseAddress!, bytesPerRow * height) + } + } else { + rgbaData.withUnsafeBytes { bytes in + self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes.baseAddress!, bytesPerRow: bytesPerRow) + } + } + } + } + + private weak var pool: TextureStoragePool? + let content: Content + private var isInvalidated: Bool = false + + init(pool: TextureStoragePool, content: Content) { + self.pool = pool + self.content = content + } + + deinit { + if !self.isInvalidated { + self.pool?.recycle(content: self.content) + } + } + } + + private final class Frame { + let duration: Double + let textureY: TextureStorage + let textureU: TextureStorage + let textureV: TextureStorage + let textureA: TextureStorage + + var remainingDuration: Double + + init?(device: MTLDevice, textureY: TextureStorage, textureU: TextureStorage, textureV: TextureStorage, textureA: TextureStorage, data: AnimationCacheItemFrame, duration: Double) { + self.duration = duration + self.remainingDuration = duration + + self.textureY = textureY + self.textureU = textureU + self.textureV = textureV + self.textureA = textureA + + switch data.format { + case .rgba: + return nil + case let .yuva(y, u, v, a): + self.textureY.content.replace(rgbaData: y.data, width: y.width, height: y.height, bytesPerRow: y.bytesPerRow) + self.textureU.content.replace(rgbaData: u.data, width: u.width, height: u.height, bytesPerRow: u.bytesPerRow) + self.textureV.content.replace(rgbaData: v.data, width: v.width, height: v.height, bytesPerRow: v.bytesPerRow) + self.textureA.content.replace(rgbaData: a.data, width: a.width, height: a.height, bytesPerRow: a.bytesPerRow) + } + } + } + + private final class ItemContext { + static let queue = Queue(name: "MultiAnimationMetalRendererImpl", qos: .default) + + private let cache: AnimationCache + private let stateUpdated: () -> Void + + private var disposable: Disposable? + private var item: AnimationCacheItem? + + private(set) var currentFrame: Frame? + private var isLoadingFrame: Bool = false + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + self.stateUpdated() + } + } + } + + var targets: [TargetReference] = [] + var slotIndex: Int + private let preferredRowAlignment: Int + + init(slotIndex: Int, preferredRowAlignment: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + self.slotIndex = slotIndex + self.preferredRowAlignment = preferredRowAlignment + self.cache = cache + self.stateUpdated = stateUpdated + + self.disposable = cache.get(sourceId: itemId, size: size, fetch: fetch).start(next: { [weak self] result in + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + strongSelf.item = result.item + strongSelf.updateIsPlaying() + + if result.item == nil { + for target in strongSelf.targets { + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: true) + } + } + } + } + }) + } + + deinit { + self.disposable?.dispose() + } + + func updateIsPlaying() { + var isPlaying = true + if self.item == nil { + isPlaying = false + } + + var shouldBeAnimating = false + for target in self.targets { + if let target = target.value { + if target.shouldBeAnimating { + shouldBeAnimating = true + break + } + } + } + if !shouldBeAnimating { + isPlaying = false + } + + self.isPlaying = isPlaying + } + + func animationTick(device: MTLDevice, texturePoolFullPlane: TextureStoragePool, texturePoolHalfPlane: TextureStoragePool, advanceTimestamp: Double) -> LoadFrameTask? { + return self.update(device: device, texturePoolFullPlane: texturePoolFullPlane, texturePoolHalfPlane: texturePoolHalfPlane, advanceTimestamp: advanceTimestamp) + } + + private func update(device: MTLDevice, texturePoolFullPlane: TextureStoragePool, texturePoolHalfPlane: TextureStoragePool, advanceTimestamp: Double) -> LoadFrameTask? { + guard let item = self.item else { + return nil + } + + if let currentFrame = self.currentFrame, !self.isLoadingFrame { + currentFrame.remainingDuration -= advanceTimestamp + } + + var frameAdvance: AnimationCacheItem.Advance? + if !self.isLoadingFrame { + if let currentFrame = self.currentFrame, advanceTimestamp > 0.0 { + let divisionFactor = advanceTimestamp / currentFrame.remainingDuration + let wholeFactor = round(divisionFactor) + if abs(wholeFactor - divisionFactor) < 0.005 { + currentFrame.remainingDuration = 0.0 + frameAdvance = .frames(Int(wholeFactor)) + } else { + currentFrame.remainingDuration -= advanceTimestamp + if currentFrame.remainingDuration <= 0.0 { + frameAdvance = .duration(currentFrame.duration + max(0.0, -currentFrame.remainingDuration)) + } + } + } else if self.currentFrame == nil { + frameAdvance = .frames(1) + } + } + + if let frameAdvance = frameAdvance, !self.isLoadingFrame { + self.isLoadingFrame = true + + let fullParameters = texturePoolFullPlane.parameters + let halfParameters = texturePoolHalfPlane.parameters + + let readyTextureY = texturePoolFullPlane.take() + let readyTextureU = texturePoolHalfPlane.take() + let readyTextureV = texturePoolHalfPlane.take() + let readyTextureA = texturePoolFullPlane.take() + let preferredRowAlignment = self.preferredRowAlignment + + return LoadFrameTask(task: { [weak self] in + let frame = item.advance(advance: frameAdvance, requestedFormat: .yuva(rowAlignment: preferredRowAlignment)) + + let textureY = readyTextureY ?? TextureStoragePool.takeNew(device: device, parameters: fullParameters, pool: texturePoolFullPlane) + let textureU = readyTextureU ?? TextureStoragePool.takeNew(device: device, parameters: halfParameters, pool: texturePoolHalfPlane) + let textureV = readyTextureV ?? TextureStoragePool.takeNew(device: device, parameters: halfParameters, pool: texturePoolHalfPlane) + let textureA = readyTextureA ?? TextureStoragePool.takeNew(device: device, parameters: fullParameters, pool: texturePoolFullPlane) + + var currentFrame: Frame? + if let frame = frame, let textureY = textureY, let textureU = textureU, let textureV = textureV, let textureA = textureA { + currentFrame = Frame(device: device, textureY: textureY, textureU: textureU, textureV: textureV, textureA: textureA, data: frame, duration: frame.duration) + } + + return { + guard let strongSelf = self else { + return + } + + strongSelf.isLoadingFrame = false + + if let currentFrame = currentFrame { + strongSelf.currentFrame = currentFrame + } + } + }) + } + + return nil + } + } + + private final class SurfaceLayer: CAMetalLayer { + private let cellSize: CGSize + private let stateUpdated: () -> Void + + private let metalDevice: MTLDevice + private let commandQueue: MTLCommandQueue + private let renderPipelineState: MTLRenderPipelineState + + private let texturePoolFullPlane: TextureStoragePool + private let texturePoolHalfPlane: TextureStoragePool + + private let preferredRowAlignment: Int + + private let slotCount: Int + private let slotsX: Int + private let slotsY: Int + private var itemContexts: [String: ItemContext] = [:] + private var slotToItemId: [String?] + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + self.stateUpdated() + } + } + } + + public init(cellSize: CGSize, stateUpdated: @escaping () -> Void) { + self.cellSize = cellSize + self.stateUpdated = stateUpdated + + let resolutionX = max(1, (1024 / Int(cellSize.width))) * Int(cellSize.width) + let resolutionY = max(1, (1024 / Int(cellSize.height))) * Int(cellSize.height) + self.slotsX = resolutionX / Int(cellSize.width) + self.slotsY = resolutionY / Int(cellSize.height) + let drawableSize = CGSize(width: cellSize.width * CGFloat(self.slotsX), height: cellSize.height * CGFloat(self.slotsY)) + + self.slotCount = (Int(drawableSize.width) / Int(cellSize.width)) * (Int(drawableSize.height) / Int(cellSize.height)) + self.slotToItemId = (0 ..< self.slotCount).map { _ in nil } + + self.metalDevice = MTLCreateSystemDefaultDevice()! + self.commandQueue = self.metalDevice.makeCommandQueue()! + + let mainBundle = Bundle(for: MultiAnimationMetalRendererImpl.self) + + guard let path = mainBundle.path(forResource: "MultiAnimationRendererBundle", ofType: "bundle") else { + preconditionFailure() + } + guard let bundle = Bundle(path: path) else { + preconditionFailure() + } + guard let defaultLibrary = try? self.metalDevice.makeDefaultLibrary(bundle: bundle) else { + preconditionFailure() + } + + self.renderPipelineState = makePipelineState(device: self.metalDevice, library: defaultLibrary, vertexProgram: "multiAnimationVertex", fragmentProgram: "multiAnimationFragment")! + + self.texturePoolFullPlane = TextureStoragePool(width: Int(self.cellSize.width), height: Int(self.cellSize.height), format: .r) + self.texturePoolHalfPlane = TextureStoragePool(width: Int(self.cellSize.width) / 2, height: Int(self.cellSize.height) / 2, format: .r) + + self.preferredRowAlignment = TextureStorage.Content.rowAlignment(device: self.metalDevice, format: .r) + + super.init() + + self.device = self.metalDevice + self.maximumDrawableCount = 2 + //self.metalLayer.presentsWithTransaction = true + self.contentsScale = 1.0 + + self.drawableSize = drawableSize + + self.pixelFormat = .bgra8Unorm + self.framebufferOnly = true + self.allowsNextDrawableTimeout = true + self.isOpaque = false + } + + override public init(layer: Any) { + preconditionFailure() + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func action(forKey event: String) -> CAAction? { + return nullAction + } + + func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable? { + if size != self.cellSize { + return nil + } + + let targetId = target.id + + if self.itemContexts[itemId] == nil { + for i in 0 ..< self.slotCount { + if self.slotToItemId[i] == nil { + self.slotToItemId[i] = itemId + self.itemContexts[itemId] = ItemContext(slotIndex: i, preferredRowAlignment: self.preferredRowAlignment, cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + break + } + } + } + + if let itemContext = self.itemContexts[itemId] { + itemContext.targets.append(TargetReference(target)) + + let deinitIndex = target.deinitCallbacks.add { [weak self, weak itemContext] in + Queue.mainQueue().async { + guard let strongSelf = self, let currentItemContext = strongSelf.itemContexts[itemId], currentItemContext === itemContext else { + return + } + strongSelf.removeTargetFromItemContext(itemId: itemId, itemContext: currentItemContext, targetId: targetId) + } + } + + let updateStateIndex = target.updateStateCallbacks.add { [weak itemContext] in + guard let itemContext = itemContext else { + return + } + itemContext.updateIsPlaying() + } + + target.contents = self.contents + + let slotX = itemContext.slotIndex % self.slotsX + let slotY = itemContext.slotIndex / self.slotsX + let totalX = CGFloat(self.slotsX) * self.cellSize.width + let totalY = CGFloat(self.slotsY) * self.cellSize.height + let contentsRect = CGRect(origin: CGPoint(x: (CGFloat(slotX) * self.cellSize.width) / totalX, y: (CGFloat(slotY) * self.cellSize.height) / totalY), size: CGSize(width: self.cellSize.width / totalX, height: self.cellSize.height / totalY)) + target.contentsRect = contentsRect + + self.isPlaying = true + + return ActionDisposable { [weak self, weak target, weak itemContext] in + Queue.mainQueue().async { + guard let strongSelf = self, let currentItemContext = strongSelf.itemContexts[itemId], currentItemContext === itemContext else { + return + } + + if let target = target { + target.deinitCallbacks.remove(deinitIndex) + target.updateStateCallbacks.remove(updateStateIndex) + } + + strongSelf.removeTargetFromItemContext(itemId: itemId, itemContext: currentItemContext, targetId: targetId) + } + } + } else { + return nil + } + } + + private func removeTargetFromItemContext(itemId: String, itemContext: ItemContext, targetId: Int64) { + if let index = itemContext.targets.firstIndex(where: { $0.id == targetId }) { + itemContext.targets.remove(at: index) + + if itemContext.targets.isEmpty { + self.slotToItemId[itemContext.slotIndex] = nil + self.itemContexts.removeValue(forKey: itemId) + + if self.itemContexts.isEmpty { + self.isPlaying = false + } + } + } + } + + private func updateIsPlaying() { + var isPlaying = false + for (_, itemContext) in self.itemContexts { + if itemContext.isPlaying { + isPlaying = true + break + } + } + + self.isPlaying = isPlaying + } + + func animationTick(advanceTimestamp: Double) -> [LoadFrameTask] { + var tasks: [LoadFrameTask] = [] + for (_, itemContext) in self.itemContexts { + if itemContext.isPlaying { + if let task = itemContext.animationTick(device: self.metalDevice, texturePoolFullPlane: self.texturePoolFullPlane, texturePoolHalfPlane: self.texturePoolHalfPlane, advanceTimestamp: advanceTimestamp) { + tasks.append(task) + } + } + } + + return tasks + } + + func redraw() { + guard let drawable = self.nextDrawable() else { + return + } + + let commandQueue = self.commandQueue + let renderPipelineState = self.renderPipelineState + let cellSize = self.cellSize + + guard let commandBuffer = commandQueue.makeCommandBuffer() else { + return + } + + /*let drawTime = CACurrentMediaTime() - timestamp + if drawTime > 9.0 / 1000.0 { + print("get time \(drawTime * 1000.0)") + }*/ + + let renderPassDescriptor = MTLRenderPassDescriptor() + renderPassDescriptor.colorAttachments[0].texture = drawable.texture + renderPassDescriptor.colorAttachments[0].loadAction = .clear + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor( + red: 0.0, + green: 0.0, + blue: 0.0, + alpha: 0.0 + ) + + guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else { + return + } + + var usedTextures: [Unmanaged] = [] + + var vertices: [Float] = [ + -1.0, -1.0, 0.0, 0.0, + 1.0, -1.0, 1.0, 0.0, + -1.0, 1.0, 0.0, 1.0, + 1.0, 1.0, 1.0, 1.0 + ] + + renderEncoder.setRenderPipelineState(renderPipelineState) + + var resolution = simd_uint2(UInt32(drawable.texture.width), UInt32(drawable.texture.height)) + renderEncoder.setVertexBytes(&resolution, length: MemoryLayout.size * 2, index: 1) + + var slotSize = simd_uint2(UInt32(cellSize.width), UInt32(cellSize.height)) + renderEncoder.setVertexBytes(&slotSize, length: MemoryLayout.size * 2, index: 2) + + for (_, itemContext) in self.itemContexts { + guard let frame = itemContext.currentFrame else { + continue + } + + let slotX = itemContext.slotIndex % self.slotsX + let slotY = self.slotsY - 1 - itemContext.slotIndex / self.slotsY + let totalX = CGFloat(self.slotsX) * self.cellSize.width + let totalY = CGFloat(self.slotsY) * self.cellSize.height + + let contentsRect = CGRect(origin: CGPoint(x: (CGFloat(slotX) * self.cellSize.width) / totalX, y: (CGFloat(slotY) * self.cellSize.height) / totalY), size: CGSize(width: self.cellSize.width / totalX, height: self.cellSize.height / totalY)) + + vertices[4 * 2 + 0] = Float(contentsRect.minX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + vertices[4 * 2 + 1] = Float(contentsRect.minY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + + vertices[4 * 3 + 0] = Float(contentsRect.maxX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + vertices[4 * 3 + 1] = Float(contentsRect.minY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + + vertices[4 * 0 + 0] = Float(contentsRect.minX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + vertices[4 * 0 + 1] = Float(contentsRect.maxY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + + vertices[4 * 1 + 0] = Float(contentsRect.maxX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + vertices[4 * 1 + 1] = Float(contentsRect.maxY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + + renderEncoder.setVertexBytes(&vertices, length: 4 * vertices.count, index: 0) + + var slotPosition = simd_uint2(UInt32(itemContext.slotIndex % self.slotsX), UInt32(itemContext.slotIndex % self.slotsY)) + renderEncoder.setVertexBytes(&slotPosition, length: MemoryLayout.size * 2, index: 3) + + usedTextures.append(Unmanaged.passRetained(frame.textureY)) + usedTextures.append(Unmanaged.passRetained(frame.textureU)) + usedTextures.append(Unmanaged.passRetained(frame.textureV)) + usedTextures.append(Unmanaged.passRetained(frame.textureA)) + renderEncoder.setFragmentTexture(frame.textureY.content.texture, index: 0) + renderEncoder.setFragmentTexture(frame.textureU.content.texture, index: 1) + renderEncoder.setFragmentTexture(frame.textureV.content.texture, index: 2) + renderEncoder.setFragmentTexture(frame.textureA.content.texture, index: 3) + + renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4, instanceCount: 1) + } + + renderEncoder.endEncoding() + + if self.presentsWithTransaction { + if Thread.isMainThread { + commandBuffer.commit() + commandBuffer.waitUntilScheduled() + drawable.present() + } else { + CATransaction.begin() + commandBuffer.commit() + commandBuffer.waitUntilScheduled() + drawable.present() + CATransaction.commit() + } + } else { + commandBuffer.addScheduledHandler { _ in + drawable.present() + } + commandBuffer.addCompletedHandler { _ in + DispatchQueue.main.async { + for texture in usedTextures { + texture.release() + } + } + } + commandBuffer.commit() + } + } + } + + private var nextSurfaceLayerIndex: Int = 1 + private var surfaceLayers: [Int: SurfaceLayer] = [:] + + private var frameSkip: Int + private var displayLink: ConstantDisplayLinkAnimator? + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + if self.isPlaying { + if self.displayLink == nil { + self.displayLink = ConstantDisplayLinkAnimator { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.animationTick() + } + self.displayLink?.frameInterval = self.frameSkip + self.displayLink?.isPaused = false + } + } else { + if let displayLink = self.displayLink { + self.displayLink = nil + displayLink.invalidate() + } + } + } + } + } + + public init() { + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.processorCount > 2 { + self.frameSkip = 1 + } else { + self.frameSkip = 2 + } + } + + private func updateIsPlaying() { + var isPlaying = false + for (_, surfaceLayer) in self.surfaceLayers { + if surfaceLayer.isPlaying { + isPlaying = true + break + } + } + + self.isPlaying = isPlaying + } + + public func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { + assert(Thread.isMainThread) + + let alignedSize = CGSize(width: CGFloat(alignUp(size: Int(size.width), align: 16)), height: CGFloat(alignUp(size: Int(size.height), align: 16))) + + for (_, surfaceLayer) in self.surfaceLayers { + if let disposable = surfaceLayer.add(target: target, cache: cache, itemId: itemId, size: alignedSize, fetch: fetch) { + return disposable + } + } + + let index = self.nextSurfaceLayerIndex + self.nextSurfaceLayerIndex += 1 + let surfaceLayer = SurfaceLayer(cellSize: alignedSize, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.surfaceLayers[index] = surfaceLayer + if let disposable = surfaceLayer.add(target: target, cache: cache, itemId: itemId, size: alignedSize, fetch: fetch) { + return disposable + } else { + return EmptyDisposable + } + } + + public func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + return false + } + + public func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + completion(false) + + return EmptyDisposable + } + + private func animationTick() { + let secondsPerFrame = Double(self.frameSkip) / 60.0 + + var tasks: [LoadFrameTask] = [] + var surfaceLayersWithTasks: [Int] = [] + for (index, surfaceLayer) in self.surfaceLayers { + var hasTasks = false + if surfaceLayer.isPlaying { + let surfaceLayerTasks = surfaceLayer.animationTick(advanceTimestamp: secondsPerFrame) + if !surfaceLayerTasks.isEmpty { + tasks.append(contentsOf: surfaceLayerTasks) + hasTasks = true + } + } + if hasTasks { + surfaceLayersWithTasks.append(index) + } + } + + if !tasks.isEmpty { + ItemContext.queue.async { [weak self] in + var completions: [() -> Void] = [] + for task in tasks { + let complete = task.task() + completions.append(complete) + } + + if !completions.isEmpty { + Queue.mainQueue().async { + for completion in completions { + completion() + } + + if let strongSelf = self { + for index in surfaceLayersWithTasks { + if let surfaceLayer = strongSelf.surfaceLayers[index] { + surfaceLayer.redraw() + } + } + } + } + } + } + } + } +} diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 97fb1cee2c..85d5dc1f55 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -3,15 +3,21 @@ import UIKit import SwiftSignalKit import Display import AnimationCache +import Accelerate public protocol MultiAnimationRenderer: AnyObject { - func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Disposable - func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String) -> Bool + func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable + func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool + func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable } +private var nextRenderTargetId: Int64 = 1 + open class MultiAnimationRenderTarget: SimpleLayer { - fileprivate let deinitCallbacks = Bag<() -> Void>() - fileprivate let updateStateCallbacks = Bag<() -> Void>() + public let id: Int64 + + let deinitCallbacks = Bag<() -> Void>() + let updateStateCallbacks = Bag<() -> Void>() public final var shouldBeAnimating: Bool = false { didSet { @@ -23,88 +29,50 @@ open class MultiAnimationRenderTarget: SimpleLayer { } } + public var blurredRepresentationBackgroundColor: UIColor? + public var blurredRepresentationTarget: CALayer? { + didSet { + if self.blurredRepresentationTarget !== oldValue { + for f in self.updateStateCallbacks.copyItems() { + f() + } + } + } + } + + public override init() { + assert(Thread.isMainThread) + + self.id = nextRenderTargetId + nextRenderTargetId += 1 + + super.init() + } + + public override init(layer: Any) { + guard let layer = layer as? MultiAnimationRenderTarget else { + preconditionFailure() + } + + self.id = layer.id + + super.init(layer: layer) + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + deinit { for f in self.deinitCallbacks.copyItems() { f() } } -} - -private func convertFrameToImage(frame: AnimationCacheItemFrame) -> UIImage? { - switch frame.format { - case let .rgba(width, height, bytesPerRow): - let context = DrawingContext(size: CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, opaque: false, bytesPerRow: bytesPerRow) - let range = frame.range - frame.data.withUnsafeBytes { bytes -> Void in - memcpy(context.bytes, bytes.baseAddress!.advanced(by: range.lowerBound), min(context.length, range.upperBound - range.lowerBound)) - } - return context.generateImage() - } -} - -private final class FrameGroup { - let image: UIImage - let size: CGSize - let frameRange: Range - let count: Int - let skip: Int - init?(item: AnimationCacheItem, baseFrameIndex: Int, count: Int, skip: Int) { - if count == 0 { - return nil - } - - assert(count % skip == 0) - - let actualCount = count / skip - - guard let firstFrame = item.getFrame(index: baseFrameIndex % item.numFrames) else { - return nil - } - - switch firstFrame.format { - case let .rgba(width, height, bytesPerRow): - let context = DrawingContext(size: CGSize(width: CGFloat(width), height: CGFloat(height * actualCount)), scale: 1.0, opaque: false, bytesPerRow: bytesPerRow) - for i in stride(from: baseFrameIndex, to: baseFrameIndex + count, by: skip) { - let frame: AnimationCacheItemFrame - if i == baseFrameIndex { - frame = firstFrame - } else { - if let nextFrame = item.getFrame(index: i % item.numFrames) { - frame = nextFrame - } else { - return nil - } - } - - let localFrameIndex = (i - baseFrameIndex) / skip - - frame.data.withUnsafeBytes { bytes -> Void in - memcpy(context.bytes.advanced(by: localFrameIndex * height * bytesPerRow), bytes.baseAddress!.advanced(by: frame.range.lowerBound), height * bytesPerRow) - } - } - - guard let image = context.generateImage() else { - return nil - } - - self.image = image - self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) - self.frameRange = baseFrameIndex ..< (baseFrameIndex + count) - self.count = count - self.skip = skip - } + open func updateDisplayPlaceholder(displayPlaceholder: Bool) { } - func contentsRect(index: Int) -> CGRect? { - if !self.frameRange.contains(index) { - return nil - } - let actualCount = self.count / self.skip - let localIndex = (index - self.frameRange.lowerBound) / self.skip - - let itemHeight = 1.0 / CGFloat(actualCount) - return CGRect(origin: CGPoint(x: 0.0, y: CGFloat(localIndex) * itemHeight), size: CGSize(width: 1.0, height: itemHeight)) + open func transitionToContents(_ contents: AnyObject) { } } @@ -117,6 +85,139 @@ private final class LoadFrameGroupTask { } private final class ItemAnimationContext { + fileprivate final class Frame { + let frame: AnimationCacheItemFrame + let duration: Double + let image: UIImage + let badgeImage: UIImage? + let size: CGSize + + var remainingDuration: Double + + private var blurredRepresentationValue: UIImage? + + init?(frame: AnimationCacheItemFrame) { + self.frame = frame + self.duration = frame.duration + self.remainingDuration = frame.duration + + switch frame.format { + case let .rgba(data, width, height, bytesPerRow): + let context = DrawingContext(size: CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, opaque: false, bytesPerRow: bytesPerRow) + + data.withUnsafeBytes { bytes -> Void in + memcpy(context.bytes, bytes.baseAddress!, height * bytesPerRow) + } + + guard let image = context.generateImage() else { + return nil + } + + self.image = image + self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) + self.badgeImage = nil + default: + return nil + } + } + + func blurredRepresentation(color: UIColor?) -> UIImage? { + if let blurredRepresentationValue = self.blurredRepresentationValue { + return blurredRepresentationValue + } + + switch frame.format { + case let .rgba(data, width, height, bytesPerRow): + let blurredWidth = 12 + let blurredHeight = 12 + let context = DrawingContext(size: CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)), scale: 1.0, opaque: true, bytesPerRow: bytesPerRow) + + let size = CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)) + + data.withUnsafeBytes { bytes -> Void in + if let dataProvider = CGDataProvider(dataInfo: nil, data: bytes.baseAddress!, size: bytes.count, releaseData: { _, _, _ in }) { + let image = CGImage( + width: width, + height: height, + bitsPerComponent: 8, + bitsPerPixel: 32, + bytesPerRow: bytesPerRow, + space: DeviceGraphicsContextSettings.shared.colorSpace, + bitmapInfo: DeviceGraphicsContextSettings.shared.transparentBitmapInfo, + provider: dataProvider, + decode: nil, + shouldInterpolate: true, + intent: .defaultIntent + ) + if let image = image { + context.withFlippedContext { c in + c.setFillColor((color ?? .white).cgColor) + c.fill(CGRect(origin: CGPoint(), size: size)) + c.draw(image, in: CGRect(origin: CGPoint(x: -size.width / 2.0, y: -size.height / 2.0), size: CGSize(width: size.width * 1.8, height: size.height * 1.8))) + } + } + } + + var destinationBuffer = vImage_Buffer() + destinationBuffer.width = UInt(blurredWidth) + destinationBuffer.height = UInt(blurredHeight) + destinationBuffer.data = context.bytes + destinationBuffer.rowBytes = context.bytesPerRow + + vImageBoxConvolve_ARGB8888(&destinationBuffer, + &destinationBuffer, + nil, + 0, 0, + UInt32(15), + UInt32(15), + nil, + vImage_Flags(kvImageTruncateKernel)) + + let divisor: Int32 = 0x1000 + + let rwgt: CGFloat = 0.3086 + let gwgt: CGFloat = 0.6094 + let bwgt: CGFloat = 0.0820 + + let adjustSaturation: CGFloat = 1.7 + + let a = (1.0 - adjustSaturation) * rwgt + adjustSaturation + let b = (1.0 - adjustSaturation) * rwgt + let c = (1.0 - adjustSaturation) * rwgt + let d = (1.0 - adjustSaturation) * gwgt + let e = (1.0 - adjustSaturation) * gwgt + adjustSaturation + let f = (1.0 - adjustSaturation) * gwgt + let g = (1.0 - adjustSaturation) * bwgt + let h = (1.0 - adjustSaturation) * bwgt + let i = (1.0 - adjustSaturation) * bwgt + adjustSaturation + + let satMatrix: [CGFloat] = [ + a, b, c, 0, + d, e, f, 0, + g, h, i, 0, + 0, 0, 0, 1 + ] + + var matrix: [Int16] = satMatrix.map { value in + return Int16(value * CGFloat(divisor)) + } + + vImageMatrixMultiply_ARGB8888(&destinationBuffer, &destinationBuffer, &matrix, divisor, nil, nil, vImage_Flags(kvImageDoNotTile)) + + context.withFlippedContext { c in + c.setFillColor((color ?? .white).withMultipliedAlpha(0.6).cgColor) + c.fill(CGRect(origin: CGPoint(), size: size)) + } + } + + self.blurredRepresentationValue = context.generateImage() + return self.blurredRepresentationValue + default: + return nil + } + } + } + static let queue = Queue(name: "ItemAnimationContext", qos: .default) private let cache: AnimationCache @@ -124,11 +225,10 @@ private final class ItemAnimationContext { private var disposable: Disposable? private var displayLink: ConstantDisplayLinkAnimator? - private var frameIndex: Int = 0 private var item: AnimationCacheItem? - private var currentFrameGroup: FrameGroup? - private var isLoadingFrameGroup: Bool = false + private var currentFrame: Frame? + private var isLoadingFrame: Bool = false private(set) var isPlaying: Bool = false { didSet { @@ -140,16 +240,16 @@ private final class ItemAnimationContext { let targets = Bag>() - init(cache: AnimationCache, itemId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + init(cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { self.cache = cache self.stateUpdated = stateUpdated - self.disposable = cache.get(sourceId: itemId, fetch: fetch).start(next: { [weak self] item in + self.disposable = cache.get(sourceId: itemId, size: size, fetch: fetch).start(next: { [weak self] result in Queue.mainQueue().async { - guard let strongSelf = self, let item = item else { + guard let strongSelf = self else { return } - strongSelf.item = item + strongSelf.item = result.item strongSelf.updateIsPlaying() } }) @@ -161,12 +261,13 @@ private final class ItemAnimationContext { } func updateAddedTarget(target: MultiAnimationRenderTarget) { - if let item = self.item, let currentFrameGroup = self.currentFrameGroup { - let currentFrame = self.frameIndex % item.numFrames - - if let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { - target.contents = currentFrameGroup.image.cgImage - target.contentsRect = contentsRect + if let currentFrame = self.currentFrame { + if let cgImage = currentFrame.image.cgImage { + target.transitionToContents(cgImage) + + if let blurredRepresentationTarget = target.blurredRepresentationTarget { + blurredRepresentationTarget.contents = currentFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage + } } } @@ -195,53 +296,73 @@ private final class ItemAnimationContext { self.isPlaying = isPlaying } - func animationTick() -> LoadFrameGroupTask? { - return self.update(advanceFrame: true) + func animationTick(advanceTimestamp: Double) -> LoadFrameGroupTask? { + return self.update(advanceTimestamp: advanceTimestamp) } - private func update(advanceFrame: Bool) -> LoadFrameGroupTask? { + private func update(advanceTimestamp: Double) -> LoadFrameGroupTask? { guard let item = self.item else { return nil } - let currentFrame = self.frameIndex % item.numFrames + var frameAdvance: AnimationCacheItem.Advance? + if !self.isLoadingFrame { + if let currentFrame = self.currentFrame, advanceTimestamp > 0.0 { + let divisionFactor = advanceTimestamp / currentFrame.remainingDuration + let wholeFactor = round(divisionFactor) + if abs(wholeFactor - divisionFactor) < 0.005 { + currentFrame.remainingDuration = 0.0 + frameAdvance = .frames(Int(wholeFactor)) + } else { + currentFrame.remainingDuration -= advanceTimestamp + if currentFrame.remainingDuration <= 0.0 { + frameAdvance = .duration(currentFrame.duration + max(0.0, -currentFrame.remainingDuration)) + } + } + } else if self.currentFrame == nil { + frameAdvance = .frames(1) + } + } - if let currentFrameGroup = self.currentFrameGroup, currentFrameGroup.frameRange.contains(currentFrame) { - } else if !self.isLoadingFrameGroup { - self.currentFrameGroup = nil - self.isLoadingFrameGroup = true + if let frameAdvance = frameAdvance, !self.isLoadingFrame { + self.isLoadingFrame = true return LoadFrameGroupTask(task: { [weak self] in - let possibleCounts: [Int] = [10, 12, 14, 16, 18, 20] - let countIndex = Int.random(in: 0 ..< possibleCounts.count) - let currentFrameGroup = FrameGroup(item: item, baseFrameIndex: currentFrame, count: possibleCounts[countIndex], skip: 2) + let currentFrame: Frame? + if let frame = item.advance(advance: frameAdvance, requestedFormat: .rgba) { + currentFrame = Frame(frame: frame) + } else { + currentFrame = nil + } return { guard let strongSelf = self else { return } - strongSelf.isLoadingFrameGroup = false + strongSelf.isLoadingFrame = false - if let currentFrameGroup = currentFrameGroup { - strongSelf.currentFrameGroup = currentFrameGroup + if let currentFrame = currentFrame { + strongSelf.currentFrame = currentFrame for target in strongSelf.targets.copyItems() { - target.value?.contents = currentFrameGroup.image.cgImage + if let target = target.value { + target.transitionToContents(currentFrame.image.cgImage!) + + if let blurredRepresentationTarget = target.blurredRepresentationTarget { + blurredRepresentationTarget.contents = currentFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage + } + } } - - let _ = strongSelf.update(advanceFrame: false) } } }) } - if advanceFrame { - self.frameIndex += 2 - } - - if let currentFrameGroup = self.currentFrameGroup, let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { + if let _ = self.currentFrame { for target in self.targets.copyItems() { - target.value?.contentsRect = contentsRect + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: false) + } } } @@ -251,9 +372,16 @@ private final class ItemAnimationContext { public final class MultiAnimationRendererImpl: MultiAnimationRenderer { private final class GroupContext { + private let firstFrameQueue: Queue private let stateUpdated: () -> Void - private var itemContexts: [String: ItemAnimationContext] = [:] + private struct ItemKey: Hashable { + var id: String + var width: Int + var height: Int + } + + private var itemContexts: [ItemKey: ItemAnimationContext] = [:] private(set) var isPlaying: Bool = false { didSet { @@ -263,22 +391,24 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - init(stateUpdated: @escaping () -> Void) { + init(firstFrameQueue: Queue, stateUpdated: @escaping () -> Void) { + self.firstFrameQueue = firstFrameQueue self.stateUpdated = stateUpdated } - func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Disposable { + func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { + let itemKey = ItemKey(id: itemId, width: Int(size.width), height: Int(size.height)) let itemContext: ItemAnimationContext - if let current = self.itemContexts[itemId] { + if let current = self.itemContexts[itemKey] { itemContext = current } else { - itemContext = ItemAnimationContext(cache: cache, itemId: itemId, fetch: fetch, stateUpdated: { [weak self] in + itemContext = ItemAnimationContext(cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in guard let strongSelf = self else { return } strongSelf.updateIsPlaying() }) - self.itemContexts[itemId] = itemContext + self.itemContexts[itemKey] = itemContext } let index = itemContext.targets.add(Weak(target)) @@ -286,12 +416,12 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { let deinitIndex = target.deinitCallbacks.add { [weak self, weak itemContext] in Queue.mainQueue().async { - guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemId] === itemContext else { + guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemKey] === itemContext else { return } itemContext.targets.remove(index) if itemContext.targets.isEmpty { - strongSelf.itemContexts.removeValue(forKey: itemId) + strongSelf.itemContexts.removeValue(forKey: itemKey) } } } @@ -304,7 +434,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } return ActionDisposable { [weak self, weak itemContext, weak target] in - guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemId] === itemContext else { + guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemKey] === itemContext else { return } if let target = target { @@ -313,18 +443,25 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } itemContext.targets.remove(index) if itemContext.targets.isEmpty { - strongSelf.itemContexts.removeValue(forKey: itemId) + strongSelf.itemContexts.removeValue(forKey: itemKey) } } } - func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String) -> Bool { - if let item = cache.getSynchronously(sourceId: itemId) { - guard let frameGroup = FrameGroup(item: item, baseFrameIndex: 0, count: 1, skip: 1) else { + func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + if let item = cache.getFirstFrameSynchronously(sourceId: itemId, size: size) { + guard let frame = item.advance(advance: .frames(1), requestedFormat: .rgba) else { + return false + } + guard let loadedFrame = ItemAnimationContext.Frame(frame: frame) else { return false } - target.contents = frameGroup.image.cgImage + target.contents = loadedFrame.image.cgImage + + if let blurredRepresentationTarget = target.blurredRepresentationTarget { + blurredRepresentationTarget.contents = loadedFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage + } return true } else { @@ -332,6 +469,42 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } + func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + return cache.getFirstFrame(queue: self.firstFrameQueue, sourceId: itemId, size: size, completion: { [weak target] item in + guard let item = item else { + Queue.mainQueue().async { + completion(false) + } + return + } + + let loadedFrame: ItemAnimationContext.Frame? + if let frame = item.advance(advance: .frames(1), requestedFormat: .rgba) { + loadedFrame = ItemAnimationContext.Frame(frame: frame) + } else { + loadedFrame = nil + } + + Queue.mainQueue().async { + guard let target = target else { + completion(false) + return + } + if let loadedFrame = loadedFrame { + target.contents = loadedFrame.image.cgImage + + if let blurredRepresentationTarget = target.blurredRepresentationTarget { + blurredRepresentationTarget.contents = loadedFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage + } + + completion(true) + } else { + completion(false) + } + } + }) + } + private func updateIsPlaying() { var isPlaying = false for (_, itemContext) in self.itemContexts { @@ -344,11 +517,11 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { self.isPlaying = isPlaying } - func animationTick() -> [LoadFrameGroupTask] { + func animationTick(advanceTimestamp: Double) -> [LoadFrameGroupTask] { var tasks: [LoadFrameGroupTask] = [] for (_, itemContext) in self.itemContexts { if itemContext.isPlaying { - if let task = itemContext.animationTick() { + if let task = itemContext.animationTick(advanceTimestamp: advanceTimestamp) { tasks.append(task) } } @@ -358,27 +531,41 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - private var groupContexts: [String: GroupContext] = [:] - private var displayLink: ConstantDisplayLinkAnimator? + public static let firstFrameQueue = Queue(name: "MultiAnimationRenderer-FirstFrame", qos: .userInteractive) + + private var groupContext: GroupContext? + private var frameSkip: Int + private var displayTimer: Foundation.Timer? private(set) var isPlaying: Bool = false { didSet { if self.isPlaying != oldValue { if self.isPlaying { - if self.displayLink == nil { - self.displayLink = ConstantDisplayLinkAnimator { [weak self] in + if self.displayTimer == nil { + final class TimerTarget: NSObject { + private let f: () -> Void + + init(_ f: @escaping () -> Void) { + self.f = f + } + + @objc func timerEvent() { + self.f() + } + } + let displayTimer = Foundation.Timer(timeInterval: CGFloat(self.frameSkip) / 60.0, target: TimerTarget { [weak self] in guard let strongSelf = self else { return } strongSelf.animationTick() - } - self.displayLink?.frameInterval = 2 - self.displayLink?.isPaused = false + }, selector: #selector(TimerTarget.timerEvent), userInfo: nil, repeats: true) + self.displayTimer = displayTimer + RunLoop.main.add(displayTimer, forMode: .common) } } else { - if let displayLink = self.displayLink { - self.displayLink = nil - displayLink.invalidate() + if let displayTimer = self.displayTimer { + self.displayTimer = nil + displayTimer.invalidate() } } } @@ -386,52 +573,73 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } public init() { + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.processorCount > 2 { + self.frameSkip = 1 + } else { + self.frameSkip = 2 + } } - public func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Disposable { + public func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { let groupContext: GroupContext - if let current = self.groupContexts[groupId] { + if let current = self.groupContext { groupContext = current } else { - groupContext = GroupContext(stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } strongSelf.updateIsPlaying() }) - self.groupContexts[groupId] = groupContext + self.groupContext = groupContext } - let disposable = groupContext.add(target: target, cache: cache, itemId: itemId, fetch: fetch) + let disposable = groupContext.add(target: target, cache: cache, itemId: itemId, size: size, fetch: fetch) return ActionDisposable { disposable.dispose() } } - public func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String) -> Bool { + public func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { let groupContext: GroupContext - if let current = self.groupContexts[groupId] { + if let current = self.groupContext { groupContext = current } else { - groupContext = GroupContext(stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } strongSelf.updateIsPlaying() }) - self.groupContexts[groupId] = groupContext + self.groupContext = groupContext } - return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId) + return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId, size: size) + } + + public func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + let groupContext: GroupContext + if let current = self.groupContext { + groupContext = current + } else { + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.groupContext = groupContext + } + + return groupContext.loadFirstFrame(target: target, cache: cache, itemId: itemId, size: size, completion: completion) } private func updateIsPlaying() { var isPlaying = false - for (_, groupContext) in self.groupContexts { + if let groupContext = self.groupContext { if groupContext.isPlaying { isPlaying = true - break } } @@ -439,10 +647,12 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } private func animationTick() { + let secondsPerFrame = Double(self.frameSkip) / 60.0 + var tasks: [LoadFrameGroupTask] = [] - for (_, groupContext) in self.groupContexts { + if let groupContext = self.groupContext { if groupContext.isPlaying { - tasks.append(contentsOf: groupContext.animationTick()) + tasks.append(contentsOf: groupContext.animationTick(advanceTimestamp: secondsPerFrame)) } } diff --git a/submodules/TelegramUI/Components/MultiVideoRenderer/BUILD b/submodules/TelegramUI/Components/MultiVideoRenderer/BUILD new file mode 100644 index 0000000000..e6fa67cd5f --- /dev/null +++ b/submodules/TelegramUI/Components/MultiVideoRenderer/BUILD @@ -0,0 +1,20 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "MultiVideoRenderer", + module_name = "MultiVideoRenderer", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/Display:Display", + "//submodules/SoftwareVideo:SoftwareVideo", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/MultiVideoRenderer/Sources/MultiVideoRenderer.swift b/submodules/TelegramUI/Components/MultiVideoRenderer/Sources/MultiVideoRenderer.swift new file mode 100644 index 0000000000..359224b564 --- /dev/null +++ b/submodules/TelegramUI/Components/MultiVideoRenderer/Sources/MultiVideoRenderer.swift @@ -0,0 +1,399 @@ +import Foundation +import UIKit +import SwiftSignalKit +import Display +import SoftwareVideo + +/*public protocol MultiVideoRenderer: AnyObject { + func add(groupId: String, target: MultiVideoRenderTarget, itemId: String, size: CGSize, source: @escaping (@escaping (String) -> Void) -> Disposable) -> Disposable +} + +open class MultiVideoRenderTarget: SimpleLayer { + fileprivate let deinitCallbacks = Bag<() -> Void>() + fileprivate let updateStateCallbacks = Bag<() -> Void>() + + public final var shouldBeAnimating: Bool = false { + didSet { + if self.shouldBeAnimating != oldValue { + for f in self.updateStateCallbacks.copyItems() { + f() + } + } + } + } + + deinit { + for f in self.deinitCallbacks.copyItems() { + f() + } + } + + open func updateDisplayPlaceholder(displayPlaceholder: Bool) { + } +} + +private final class ItemVideoContext { + static let queue = Queue(name: "ItemVideoContext", qos: .default) + + private let stateUpdated: () -> Void + + private var disposable: Disposable? + private var displayLink: ConstantDisplayLinkAnimator? + private var frameManager: SoftwareVideoLayerFrameManager? + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + self.stateUpdated() + } + } + } + + let targets = Bag>() + + init(itemId: String, source: @escaping (@escaping (String) -> Void) -> Disposable, stateUpdated: @escaping () -> Void) { + self.stateUpdated = stateUpdated + + self.disposable = source({ [weak self] in + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + //strongSelf.frameManager = SoftwareVideoLayerFrameManager(account: <#T##Account#>, fileReference: <#T##FileMediaReference#>, layerHolder: <#T##SampleBufferLayer#>) + strongSelf.updateIsPlaying() + + if result.item == nil { + for target in strongSelf.targets.copyItems() { + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: true) + } + } + } + } + }) + } + + deinit { + self.disposable?.dispose() + self.displayLink?.invalidate() + } + + func updateAddedTarget(target: MultiAnimationRenderTarget) { + if let item = self.item, let currentFrameGroup = self.currentFrameGroup { + let currentFrame = self.frameIndex % item.numFrames + + if let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { + target.updateDisplayPlaceholder(displayPlaceholder: false) + target.contents = currentFrameGroup.image.cgImage + target.contentsRect = contentsRect + } + } + + self.updateIsPlaying() + } + + func updateIsPlaying() { + var isPlaying = true + if self.item == nil { + isPlaying = false + } + + var shouldBeAnimating = false + for target in self.targets.copyItems() { + if let target = target.value { + if target.shouldBeAnimating { + shouldBeAnimating = true + break + } + } + } + if !shouldBeAnimating { + isPlaying = false + } + + self.isPlaying = isPlaying + } + + func animationTick() -> LoadFrameGroupTask? { + return self.update(advanceFrame: true) + } + + private func update(advanceFrame: Bool) -> LoadFrameGroupTask? { + guard let item = self.item else { + return nil + } + + let currentFrame = self.frameIndex % item.numFrames + + if let currentFrameGroup = self.currentFrameGroup, currentFrameGroup.frameRange.contains(currentFrame) { + } else if !self.isLoadingFrameGroup { + self.currentFrameGroup = nil + self.isLoadingFrameGroup = true + let frameSkip = self.frameSkip + + return LoadFrameGroupTask(task: { [weak self] in + let possibleCounts: [Int] = [10, 12, 14, 16, 18, 20] + let countIndex = Int.random(in: 0 ..< possibleCounts.count) + let currentFrameGroup = FrameGroup(item: item, baseFrameIndex: currentFrame, count: possibleCounts[countIndex], skip: frameSkip) + + return { + guard let strongSelf = self else { + return + } + + strongSelf.isLoadingFrameGroup = false + + if let currentFrameGroup = currentFrameGroup { + strongSelf.currentFrameGroup = currentFrameGroup + for target in strongSelf.targets.copyItems() { + target.value?.contents = currentFrameGroup.image.cgImage + } + + let _ = strongSelf.update(advanceFrame: false) + } + } + }) + } + + if advanceFrame { + self.frameIndex += self.frameSkip + } + + if let currentFrameGroup = self.currentFrameGroup, let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { + for target in self.targets.copyItems() { + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: false) + target.contentsRect = contentsRect + } + } + } + + return nil + } +} + +public final class MultiAnimationRendererImpl: MultiAnimationRenderer { + private final class GroupContext { + private var frameSkip: Int + private let stateUpdated: () -> Void + + private var itemContexts: [String: ItemAnimationContext] = [:] + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + self.stateUpdated() + } + } + } + + init(frameSkip: Int, stateUpdated: @escaping () -> Void) { + self.frameSkip = frameSkip + self.stateUpdated = stateUpdated + } + + func add(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { + let itemContext: ItemAnimationContext + if let current = self.itemContexts[itemId] { + itemContext = current + } else { + itemContext = ItemAnimationContext(cache: cache, itemId: itemId, size: size, frameSkip: self.frameSkip, fetch: fetch, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.itemContexts[itemId] = itemContext + } + + let index = itemContext.targets.add(Weak(target)) + itemContext.updateAddedTarget(target: target) + + let deinitIndex = target.deinitCallbacks.add { [weak self, weak itemContext] in + Queue.mainQueue().async { + guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemId] === itemContext else { + return + } + itemContext.targets.remove(index) + if itemContext.targets.isEmpty { + strongSelf.itemContexts.removeValue(forKey: itemId) + } + } + } + + let updateStateIndex = target.updateStateCallbacks.add { [weak itemContext] in + guard let itemContext = itemContext else { + return + } + itemContext.updateIsPlaying() + } + + return ActionDisposable { [weak self, weak itemContext, weak target] in + guard let strongSelf = self, let itemContext = itemContext, strongSelf.itemContexts[itemId] === itemContext else { + return + } + if let target = target { + target.deinitCallbacks.remove(deinitIndex) + target.updateStateCallbacks.remove(updateStateIndex) + } + itemContext.targets.remove(index) + if itemContext.targets.isEmpty { + strongSelf.itemContexts.removeValue(forKey: itemId) + } + } + } + + func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + if let item = cache.getSynchronously(sourceId: itemId, size: size) { + guard let frameGroup = FrameGroup(item: item, baseFrameIndex: 0, count: 1, skip: 1) else { + return false + } + + target.contents = frameGroup.image.cgImage + + return true + } else { + return false + } + } + + private func updateIsPlaying() { + var isPlaying = false + for (_, itemContext) in self.itemContexts { + if itemContext.isPlaying { + isPlaying = true + break + } + } + + self.isPlaying = isPlaying + } + + func animationTick() -> [LoadFrameGroupTask] { + var tasks: [LoadFrameGroupTask] = [] + for (_, itemContext) in self.itemContexts { + if itemContext.isPlaying { + if let task = itemContext.animationTick() { + tasks.append(task) + } + } + } + + return tasks + } + } + + private var groupContexts: [String: GroupContext] = [:] + private var frameSkip: Int + private var displayLink: ConstantDisplayLinkAnimator? + + private(set) var isPlaying: Bool = false { + didSet { + if self.isPlaying != oldValue { + if self.isPlaying { + if self.displayLink == nil { + self.displayLink = ConstantDisplayLinkAnimator { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.animationTick() + } + self.displayLink?.frameInterval = self.frameSkip + self.displayLink?.isPaused = false + } + } else { + if let displayLink = self.displayLink { + self.displayLink = nil + displayLink.invalidate() + } + } + } + } + } + + public init() { + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.activeProcessorCount > 2 { + self.frameSkip = 1 + } else { + self.frameSkip = 2 + } + } + + public func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { + let groupContext: GroupContext + if let current = self.groupContexts[groupId] { + groupContext = current + } else { + groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.groupContexts[groupId] = groupContext + } + + let disposable = groupContext.add(target: target, cache: cache, itemId: itemId, size: size, fetch: fetch) + + return ActionDisposable { + disposable.dispose() + } + } + + public func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + let groupContext: GroupContext + if let current = self.groupContexts[groupId] { + groupContext = current + } else { + groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.groupContexts[groupId] = groupContext + } + + return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId, size: size) + } + + private func updateIsPlaying() { + var isPlaying = false + for (_, groupContext) in self.groupContexts { + if groupContext.isPlaying { + isPlaying = true + break + } + } + + self.isPlaying = isPlaying + } + + private func animationTick() { + var tasks: [LoadFrameGroupTask] = [] + for (_, groupContext) in self.groupContexts { + if groupContext.isPlaying { + tasks.append(contentsOf: groupContext.animationTick()) + } + } + + if !tasks.isEmpty { + ItemAnimationContext.queue.async { + var completions: [() -> Void] = [] + for task in tasks { + let complete = task.task() + completions.append(complete) + } + + if !completions.isEmpty { + Queue.mainQueue().async { + for completion in completions { + completion() + } + } + } + } + } + } +} +*/ diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/BUILD b/submodules/TelegramUI/Components/TextNodeWithEntities/BUILD new file mode 100644 index 0000000000..402cbbd90a --- /dev/null +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/BUILD @@ -0,0 +1,24 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "TextNodeWithEntities", + module_name = "TextNodeWithEntities", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/AsyncDisplayKit:AsyncDisplayKit", + "//submodules/Display:Display", + "//submodules/TextFormat:TextFormat", + "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift new file mode 100644 index 0000000000..8ffe7cf143 --- /dev/null +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -0,0 +1,547 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import EmojiTextAttachmentView +import TextFormat +import AccountContext +import AnimationCache +import MultiAnimationRenderer +import TelegramCore + +private final class InlineStickerItem: Hashable { + let emoji: ChatTextInputTextCustomEmojiAttribute + let file: TelegramMediaFile? + let fontSize: CGFloat + + init(emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, fontSize: CGFloat) { + self.emoji = emoji + self.file = file + self.fontSize = fontSize + } + + func hash(into hasher: inout Hasher) { + hasher.combine(emoji.fileId) + hasher.combine(self.fontSize) + } + + static func ==(lhs: InlineStickerItem, rhs: InlineStickerItem) -> Bool { + if lhs.emoji.fileId != rhs.emoji.fileId { + return false + } + if lhs.file?.fileId != rhs.file?.fileId { + return false + } + if lhs.fontSize != rhs.fontSize { + return false + } + return true + } +} + +private final class RunDelegateData { + let ascent: CGFloat + let descent: CGFloat + let width: CGFloat + + init(ascent: CGFloat, descent: CGFloat, width: CGFloat) { + self.ascent = ascent + self.descent = descent + self.width = width + } +} + +public final class TextNodeWithEntities { + public final class Arguments { + public let context: AccountContext + public let cache: AnimationCache + public let renderer: MultiAnimationRenderer + public let placeholderColor: UIColor + public let attemptSynchronous: Bool + + public init( + context: AccountContext, + cache: AnimationCache, + renderer: MultiAnimationRenderer, + placeholderColor: UIColor, + attemptSynchronous: Bool + ) { + self.context = context + self.cache = cache + self.renderer = renderer + self.placeholderColor = placeholderColor + self.attemptSynchronous = attemptSynchronous + } + + public func withUpdatedPlaceholderColor(_ color: UIColor) -> Arguments { + return Arguments( + context: self.context, + cache: self.cache, + renderer: self.renderer, + placeholderColor: color, + attemptSynchronous: self.attemptSynchronous + ) + } + } + + public let textNode: TextNode + private var inlineStickerItemLayers: [InlineStickerItemLayer.Key: InlineStickerItemLayer] = [:] + + public var visibilityRect: CGRect? { + didSet { + if !self.inlineStickerItemLayers.isEmpty && oldValue != self.visibilityRect { + for (_, itemLayer) in self.inlineStickerItemLayers { + let isItemVisible: Bool + if let visibilityRect = self.visibilityRect { + if itemLayer.frame.intersects(visibilityRect) { + isItemVisible = true + } else { + isItemVisible = false + } + } else { + isItemVisible = false + } + itemLayer.isVisibleForAnimations = isItemVisible + } + } + } + } + + public init() { + self.textNode = TextNode() + } + + private init(textNode: TextNode) { + self.textNode = textNode + } + + public static func asyncLayout(_ maybeNode: TextNodeWithEntities?) -> (TextNodeLayoutArguments) -> (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities) { + let makeLayout = TextNode.asyncLayout(maybeNode?.textNode) + return { [weak maybeNode] arguments in + var updatedString: NSAttributedString? + if let sourceString = arguments.attributedString { + let string = NSMutableAttributedString(attributedString: sourceString) + + var fullRange = NSRange(location: 0, length: string.length) + while true { + var found = false + string.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: fullRange, options: [], using: { value, range, stop in + if let value = value as? ChatTextInputTextCustomEmojiAttribute, let font = string.attribute(.font, at: range.location, effectiveRange: nil) as? UIFont { + let updatedSubstring = NSMutableAttributedString(string: "&") + + let replacementRange = NSRange(location: 0, length: updatedSubstring.length) + updatedSubstring.addAttributes(string.attributes(at: range.location, effectiveRange: nil), range: replacementRange) + updatedSubstring.addAttribute(NSAttributedString.Key("Attribute__EmbeddedItem"), value: InlineStickerItem(emoji: value, file: value.file, fontSize: font.pointSize), range: replacementRange) + updatedSubstring.addAttribute(originalTextAttributeKey, value: string.attributedSubstring(from: range).string, range: replacementRange) + + let itemSize = (font.pointSize * 24.0 / 17.0) + + let runDelegateData = RunDelegateData( + ascent: font.ascender, + descent: font.descender, + width: itemSize + ) + var callbacks = CTRunDelegateCallbacks( + version: kCTRunDelegateCurrentVersion, + dealloc: { dataRef in + Unmanaged.fromOpaque(dataRef).release() + }, + getAscent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().ascent + }, + getDescent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().descent + }, + getWidth: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().width + } + ) + + if let runDelegate = CTRunDelegateCreate(&callbacks, Unmanaged.passRetained(runDelegateData).toOpaque()) { + updatedSubstring.addAttribute(NSAttributedString.Key(kCTRunDelegateAttributeName as String), value: runDelegate, range: replacementRange) + } + + string.replaceCharacters(in: range, with: updatedSubstring) + let updatedRange = NSRange(location: range.location, length: updatedSubstring.length) + + found = true + stop.pointee = ObjCBool(true) + fullRange = NSRange(location: updatedRange.upperBound, length: fullRange.upperBound - range.upperBound) + } + }) + if !found { + break + } + } + + updatedString = string + } + + let (layout, apply) = makeLayout(arguments.withAttributedString(updatedString)) + return (layout, { applyArguments in + let result = apply() + + if let maybeNode = maybeNode { + if let applyArguments = applyArguments { + maybeNode.updateInlineStickers(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false) + } + + return maybeNode + } else { + let resultNode = TextNodeWithEntities(textNode: result) + + if let applyArguments = applyArguments { + resultNode.updateInlineStickers(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false) + } + + return resultNode + } + }) + } + } + + private func isItemVisible(itemRect: CGRect) -> Bool { + if let visibilityRect = self.visibilityRect { + return itemRect.intersects(visibilityRect) + } else { + return false + } + } + + private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor, attemptSynchronousLoad: Bool) { + var nextIndexById: [Int64: Int] = [:] + var validIds: [InlineStickerItemLayer.Key] = [] + + if let textLayout = textLayout { + for item in textLayout.embeddedItems { + if let stickerItem = item.value as? InlineStickerItem { + let index: Int + if let currentNext = nextIndexById[stickerItem.emoji.fileId] { + index = currentNext + } else { + index = 0 + } + nextIndexById[stickerItem.emoji.fileId] = index + 1 + let id = InlineStickerItemLayer.Key(id: stickerItem.emoji.fileId, index: index) + validIds.append(id) + + let itemSize = floor(stickerItem.fontSize * 24.0 / 17.0) + + var itemFrame = CGRect(origin: item.rect.offsetBy(dx: textLayout.insets.left, dy: textLayout.insets.top + 1.0).center, size: CGSize()).insetBy(dx: -itemSize / 2.0, dy: -itemSize / 2.0) + itemFrame.origin.x = floorToScreenPixels(itemFrame.origin.x) + itemFrame.origin.y = floorToScreenPixels(itemFrame.origin.y) + + let itemLayer: InlineStickerItemLayer + if let current = self.inlineStickerItemLayers[id] { + itemLayer = current + } else { + let pointSize = floor(itemSize * 1.3) + itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: pointSize, height: pointSize)) + self.inlineStickerItemLayers[id] = itemLayer + self.textNode.layer.addSublayer(itemLayer) + + itemLayer.isVisibleForAnimations = self.isItemVisible(itemRect: itemFrame) + } + + itemLayer.frame = itemFrame + } + } + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, itemLayer) in self.inlineStickerItemLayers { + if !validIds.contains(key) { + removeKeys.append(key) + itemLayer.removeFromSuperlayer() + } + } + for key in removeKeys { + self.inlineStickerItemLayers.removeValue(forKey: key) + } + } +} + +public class ImmediateTextNodeWithEntities: TextNode { + public var attributedText: NSAttributedString? + public var textAlignment: NSTextAlignment = .natural + public var verticalAlignment: TextVerticalAlignment = .top + public var truncationType: CTLineTruncationType = .end + public var maximumNumberOfLines: Int = 1 + public var lineSpacing: CGFloat = 0.0 + public var insets: UIEdgeInsets = UIEdgeInsets() + public var textShadowColor: UIColor? + public var textStroke: (UIColor, CGFloat)? + public var cutout: TextNodeCutout? + public var displaySpoilers = false + + public var arguments: TextNodeWithEntities.Arguments? + + private var inlineStickerItemLayers: [InlineStickerItemLayer.Key: InlineStickerItemLayer] = [:] + + public var visibility: Bool = false { + didSet { + if !self.inlineStickerItemLayers.isEmpty && oldValue != self.visibility { + for (_, itemLayer) in self.inlineStickerItemLayers { + let isItemVisible: Bool = self.visibility + itemLayer.isVisibleForAnimations = isItemVisible + } + } + } + } + + public var truncationMode: NSLineBreakMode { + get { + switch self.truncationType { + case .start: + return .byTruncatingHead + case .middle: + return .byTruncatingMiddle + case .end: + return .byTruncatingTail + @unknown default: + return .byTruncatingTail + } + } set(value) { + switch value { + case .byTruncatingHead: + self.truncationType = .start + case .byTruncatingMiddle: + self.truncationType = .middle + case .byTruncatingTail: + self.truncationType = .end + default: + self.truncationType = .end + } + } + } + + private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer? + private var linkHighlightingNode: LinkHighlightingNode? + + public var linkHighlightColor: UIColor? + + public var trailingLineWidth: CGFloat? + + var constrainedSize: CGSize? + + public var highlightAttributeAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? { + didSet { + if self.isNodeLoaded { + self.updateInteractiveActions() + } + } + } + + public var tapAttributeAction: (([NSAttributedString.Key: Any], Int) -> Void)? + public var longTapAttributeAction: (([NSAttributedString.Key: Any], Int) -> Void)? + + private func processedAttributedText() -> NSAttributedString? { + var updatedString: NSAttributedString? + if let sourceString = self.attributedText { + let string = NSMutableAttributedString(attributedString: sourceString) + + let fullRange = NSRange(location: 0, length: string.length) + string.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: fullRange, options: [], using: { value, range, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + if let font = string.attribute(.font, at: range.location, effectiveRange: nil) as? UIFont { + string.addAttribute(NSAttributedString.Key("Attribute__EmbeddedItem"), value: InlineStickerItem(emoji: value, file: value.file, fontSize: font.pointSize), range: range) + } + } + }) + + updatedString = string + } + return updatedString + } + + public func updateLayout(_ constrainedSize: CGSize) -> CGSize { + self.constrainedSize = constrainedSize + + let makeLayout = TextNode.asyncLayout(self) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.processedAttributedText(), backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke, displaySpoilers: self.displaySpoilers)) + + let _ = apply() + + if let arguments = self.arguments { + self.updateInlineStickers(context: arguments.context, cache: arguments.cache, renderer: arguments.renderer, textLayout: layout, placeholderColor: arguments.placeholderColor) + } + + if layout.numberOfLines > 1 { + self.trailingLineWidth = layout.trailingLineWidth + } else { + self.trailingLineWidth = nil + } + return layout.size + } + + private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor) { + var nextIndexById: [Int64: Int] = [:] + var validIds: [InlineStickerItemLayer.Key] = [] + + if let textLayout = textLayout { + for item in textLayout.embeddedItems { + if let stickerItem = item.value as? InlineStickerItem { + let index: Int + if let currentNext = nextIndexById[stickerItem.emoji.fileId] { + index = currentNext + } else { + index = 0 + } + nextIndexById[stickerItem.emoji.fileId] = index + 1 + let id = InlineStickerItemLayer.Key(id: stickerItem.emoji.fileId, index: index) + validIds.append(id) + + let itemSize = floor(stickerItem.fontSize * 24.0 / 17.0) + + let itemFrame = CGRect(origin: item.rect.offsetBy(dx: textLayout.insets.left, dy: textLayout.insets.top + 0.0).center, size: CGSize()).insetBy(dx: -itemSize / 2.0, dy: -itemSize / 2.0) + + let itemLayer: InlineStickerItemLayer + if let current = self.inlineStickerItemLayers[id] { + itemLayer = current + } else { + let pointSize = floor(itemSize * 1.3) + itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: pointSize, height: pointSize)) + self.inlineStickerItemLayers[id] = itemLayer + self.layer.addSublayer(itemLayer) + + itemLayer.isVisibleForAnimations = self.visibility + } + + itemLayer.frame = itemFrame + } + } + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, itemLayer) in self.inlineStickerItemLayers { + if !validIds.contains(key) { + removeKeys.append(key) + itemLayer.removeFromSuperlayer() + } + } + for key in removeKeys { + self.inlineStickerItemLayers.removeValue(forKey: key) + } + } + + public func updateLayoutInfo(_ constrainedSize: CGSize) -> ImmediateTextNodeLayoutInfo { + self.constrainedSize = constrainedSize + + let makeLayout = TextNode.asyncLayout(self) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.processedAttributedText(), backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) + + let _ = apply() + + if let arguments = self.arguments { + self.updateInlineStickers(context: arguments.context, cache: arguments.cache, renderer: arguments.renderer, textLayout: layout, placeholderColor: arguments.placeholderColor) + } + + return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated, numberOfLines: layout.numberOfLines) + } + + public func updateLayoutFullInfo(_ constrainedSize: CGSize) -> TextNodeLayout { + self.constrainedSize = constrainedSize + + let makeLayout = TextNode.asyncLayout(self) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.processedAttributedText(), backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) + + let _ = apply() + + if let arguments = self.arguments { + self.updateInlineStickers(context: arguments.context, cache: arguments.cache, renderer: arguments.renderer, textLayout: layout, placeholderColor: arguments.placeholderColor) + } + + return layout + } + + public func redrawIfPossible() { + if let constrainedSize = self.constrainedSize { + let _ = self.updateLayout(constrainedSize) + } + } + + override public func didLoad() { + super.didLoad() + + self.updateInteractiveActions() + } + + private func updateInteractiveActions() { + if self.highlightAttributeAction != nil { + if self.tapRecognizer == nil { + let tapRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapAction(_:))) + tapRecognizer.highlight = { [weak self] point in + if let strongSelf = self { + var rects: [CGRect]? + if let point = point { + if let (index, attributes) = strongSelf.attributesAtPoint(CGPoint(x: point.x, y: point.y)) { + if let selectedAttribute = strongSelf.highlightAttributeAction?(attributes) { + let initialRects = strongSelf.lineAndAttributeRects(name: selectedAttribute.rawValue, at: index) + if let initialRects = initialRects, case .center = strongSelf.textAlignment { + var mappedRects: [CGRect] = [] + for i in 0 ..< initialRects.count { + let lineRect = initialRects[i].0 + var itemRect = initialRects[i].1 + itemRect.origin.x = floor((strongSelf.bounds.size.width - lineRect.width) / 2.0) + itemRect.origin.x + mappedRects.append(itemRect) + } + rects = mappedRects + } else { + rects = strongSelf.attributeRects(name: selectedAttribute.rawValue, at: index) + } + } + } + } + + if let rects = rects { + let linkHighlightingNode: LinkHighlightingNode + if let current = strongSelf.linkHighlightingNode { + linkHighlightingNode = current + } else { + linkHighlightingNode = LinkHighlightingNode(color: strongSelf.linkHighlightColor ?? .clear) + strongSelf.linkHighlightingNode = linkHighlightingNode + strongSelf.addSubnode(linkHighlightingNode) + } + linkHighlightingNode.frame = strongSelf.bounds + linkHighlightingNode.updateRects(rects.map { $0.offsetBy(dx: 0.0, dy: 0.0) }) + } else if let linkHighlightingNode = strongSelf.linkHighlightingNode { + strongSelf.linkHighlightingNode = nil + linkHighlightingNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak linkHighlightingNode] _ in + linkHighlightingNode?.removeFromSupernode() + }) + } + } + } + self.view.addGestureRecognizer(tapRecognizer) + } + } else if let tapRecognizer = self.tapRecognizer { + self.tapRecognizer = nil + self.view.removeGestureRecognizer(tapRecognizer) + } + } + + @objc private func tapAction(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { + switch recognizer.state { + case .ended: + if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { + switch gesture { + case .tap: + if let (index, attributes) = self.attributesAtPoint(CGPoint(x: location.x, y: location.y)) { + self.tapAttributeAction?(attributes, index) + } + case .longTap: + if let (index, attributes) = self.attributesAtPoint(CGPoint(x: location.x, y: location.y)) { + self.longTapAttributeAction?(attributes, index) + } + default: + break + } + } + default: + break + } + } +} diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/BUILD b/submodules/TelegramUI/Components/VideoAnimationCache/BUILD new file mode 100644 index 0000000000..7eb3cd35c3 --- /dev/null +++ b/submodules/TelegramUI/Components/VideoAnimationCache/BUILD @@ -0,0 +1,21 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "VideoAnimationCache", + module_name = "VideoAnimationCache", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", + "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", + "//submodules/Display:Display", + "//submodules/AnimatedStickerNode:AnimatedStickerNode", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift new file mode 100644 index 0000000000..80190fc36f --- /dev/null +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -0,0 +1,59 @@ +import Foundation +import UIKit +import AnimationCache +import Display +import AnimatedStickerNode +import SwiftSignalKit + +private func roundUp(_ numToRound: Int, multiple: Int) -> Int { + if multiple == 0 { + return numToRound + } + + let remainder = numToRound % multiple + if remainder == 0 { + return numToRound; + } + + return numToRound + multiple - remainder +} + +public func cacheVideoAnimation(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter) { + writer.queue.async { + guard let frameSource = makeVideoStickerDirectFrameSource(queue: writer.queue, path: path, width: roundUp(width, multiple: 16), height: roundUp(height, multiple: 16), cachePathPrefix: nil, unpremultiplyAlpha: false) else { + return + } + let frameDuration = 1.0 / Double(frameSource.frameRate) + while true { + if writer.isCancelled { + break + } + if let frame = frameSource.takeFrame(draw: true) { + if case .argb = frame.type { + let bytesPerRow = frame.bytesPerRow + + writer.add(with: { surface in + frame.data.withUnsafeBytes { bytes -> Void in + let sourceArgb = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) + if surface.bytesPerRow == bytesPerRow { + memcpy(surface.argb, sourceArgb, min(surface.length, bytes.count)) + } else { + let copyBytesPerRow = min(surface.bytesPerRow, bytesPerRow) + for y in 0 ..< surface.height { + memcpy(surface.argb.advanced(by: y * surface.bytesPerRow), sourceArgb.advanced(by: y * bytesPerRow), copyBytesPerRow) + } + } + } + return frameDuration + }, proposedWidth: frame.width, proposedHeight: frame.height) + } else { + break + } + } else { + break + } + } + + writer.finish() + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Contents.json new file mode 100644 index 0000000000..c987153332 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Size=24px, Direction=Right.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Size=24px, Direction=Right.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Size=24px, Direction=Right.pdf new file mode 100644 index 0000000000..2896dfef33 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Arrow.imageset/Size=24px, Direction=Right.pdf @@ -0,0 +1,92 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +-0.000000 1.000000 1.000000 0.000000 1.540161 6.000000 cm +0.000000 0.000000 0.000000 scn +-0.470226 7.930065 m +-0.729925 7.670366 -0.729925 7.249311 -0.470226 6.989613 c +-0.210527 6.729914 0.210527 6.729914 0.470226 6.989613 c +-0.470226 7.930065 l +h +6.000000 13.459839 m +6.470226 13.930065 l +6.210527 14.189764 5.789473 14.189764 5.529774 13.930065 c +6.000000 13.459839 l +h +11.529774 6.989613 m +11.789473 6.729914 12.210527 6.729914 12.470226 6.989613 c +12.729925 7.249311 12.729925 7.670366 12.470226 7.930065 c +11.529774 6.989613 l +h +0.470226 6.989613 m +6.470226 12.989613 l +5.529774 13.930065 l +-0.470226 7.930065 l +0.470226 6.989613 l +h +5.529774 12.989613 m +11.529774 6.989613 l +12.470226 7.930065 l +6.470226 13.930065 l +5.529774 12.989613 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 783 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.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 +0000000873 00000 n +0000000895 00000 n +0000001068 00000 n +0000001142 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1201 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json new file mode 100644 index 0000000000..d4b2093823 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "backspace_24.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/backspace_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/backspace_24.svg new file mode 100644 index 0000000000..3907ddf696 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/backspace_24.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json new file mode 100644 index 0000000000..bf55af4ccb --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "emoji.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/emoji.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/emoji.svg new file mode 100644 index 0000000000..cf7371e770 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/emoji.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json new file mode 100644 index 0000000000..1e503c705b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "gifs.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/gifs.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/gifs.svg new file mode 100644 index 0000000000..b1f69cab65 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/gifs.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json new file mode 100644 index 0000000000..a4c1cddbca --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "keyboard_24.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/keyboard_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/keyboard_24.svg new file mode 100644 index 0000000000..6134e3e7fa --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/keyboard_24.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/Contents.json new file mode 100644 index 0000000000..7db6c363c6 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "trending_243.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/trending_243.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/trending_243.pdf new file mode 100644 index 0000000000..bca27efbc1 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/trending_243.pdf @@ -0,0 +1,97 @@ +%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.833328 3.103020 cm +0.000000 0.000000 0.000000 scn +18.968134 6.422131 m +9.921612 0.841606 l +8.959215 0.264313 7.804340 0.649178 7.226903 1.418903 c +7.034423 1.803768 6.841944 2.381062 7.034423 2.958355 c +8.381778 8.538876 l +8.959216 10.463194 10.306571 12.195080 12.038884 13.157240 c +21.855324 17.968033 l +22.240282 18.160465 22.432762 18.737761 22.240282 19.122625 c +22.047804 19.507488 21.662846 19.699921 21.277887 19.699921 c +10.306570 17.775602 l +7.996819 17.390739 5.879548 17.968033 3.954755 19.507488 c +0.682608 22.393965 l +-0.087309 22.971260 -0.279788 24.318281 0.490129 25.088009 c +0.875087 25.472872 1.260046 25.857737 1.837484 25.857737 c +12.423841 26.627464 l +13.193759 26.627464 13.771195 27.204758 14.156155 27.782055 c +18.198217 37.788506 l +18.583178 38.750664 19.738050 39.327961 20.892927 38.943096 c +21.470366 38.750664 21.855324 38.365803 22.047804 37.788506 c +26.089869 27.974487 l +26.282347 27.204758 27.052263 26.819897 27.822180 26.819897 c +38.408539 26.050167 l +39.563416 26.050167 40.333332 25.088009 40.333332 23.933418 c +40.333332 23.356125 39.948372 22.971260 39.563416 22.586397 c +31.479284 15.658852 l +30.901848 15.081556 30.709370 14.311831 30.901850 13.734535 c +33.404076 3.343220 l +33.596558 2.188629 33.019119 1.226471 31.864244 0.841606 c +31.286808 0.649174 30.901846 0.841606 30.324409 1.034039 c +21.277887 6.614559 l +20.507969 6.806992 19.738052 6.806995 18.968134 6.422131 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1493 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 44.000000 44.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 +0000001583 00000 n +0000001606 00000 n +0000001779 00000 n +0000001853 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1912 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json new file mode 100644 index 0000000000..ee96d83980 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "search_24.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/search_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/search_24.svg new file mode 100644 index 0000000000..aebf081900 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/search_24.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json new file mode 100644 index 0000000000..92f837ea2b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "keyboard_2444.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/keyboard_2444.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/keyboard_2444.svg new file mode 100644 index 0000000000..74f7d2fe51 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/keyboard_2444.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json new file mode 100644 index 0000000000..e87af5cac3 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "stickers_24.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/stickers_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/stickers_24.svg new file mode 100644 index 0000000000..9ef1751164 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/stickers_24.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Contents.json index f9b52ce6f6..8dfe0c8a9c 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "StickersGroupCross@2x-1.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "StickersGroupCross@3x.png", - "scale" : "3x" + "filename" : "Frame 1.svg", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Frame 1.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Frame 1.svg new file mode 100644 index 0000000000..8b5fc9d694 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Frame 1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@2x-1.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@2x-1.png deleted file mode 100644 index 3c45e3b85a..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@2x-1.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@3x.png deleted file mode 100644 index 44dfdfabb3..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@3x.png and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/Contents.json new file mode 100644 index 0000000000..776f120f42 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "addstickers.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/addstickers.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/addstickers.pdf new file mode 100644 index 0000000000..bf0428ec3f --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/addstickers.pdf @@ -0,0 +1,103 @@ +%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 8.000000 2.000000 cm +0.000000 0.000000 0.000000 scn +1.000000 10.000000 m +1.000000 10.552285 0.552285 11.000000 0.000000 11.000000 c +-0.552285 11.000000 -1.000000 10.552285 -1.000000 10.000000 c +1.000000 10.000000 l +h +-1.000000 2.000000 m +-1.000000 1.447715 -0.552285 1.000000 0.000000 1.000000 c +0.552285 1.000000 1.000000 1.447715 1.000000 2.000000 c +-1.000000 2.000000 l +h +-1.000000 10.000000 m +-1.000000 2.000000 l +1.000000 2.000000 l +1.000000 10.000000 l +-1.000000 10.000000 l +h +f +n +Q +q +0.000000 1.000000 -1.000000 0.000000 6.000000 8.000000 cm +0.000000 0.000000 0.000000 scn +1.000000 2.000000 m +1.000000 2.552285 0.552285 3.000000 0.000000 3.000000 c +-0.552285 3.000000 -1.000000 2.552285 -1.000000 2.000000 c +1.000000 2.000000 l +h +-1.000000 -6.000000 m +-1.000000 -6.552285 -0.552285 -7.000000 0.000000 -7.000000 c +0.552285 -7.000000 1.000000 -6.552285 1.000000 -6.000000 c +-1.000000 -6.000000 l +h +-1.000000 2.000000 m +-1.000000 -6.000000 l +1.000000 -6.000000 l +1.000000 2.000000 l +-1.000000 2.000000 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 1083 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 16.000000 16.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 +0000001173 00000 n +0000001196 00000 n +0000001369 00000 n +0000001443 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1502 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/Contents.json new file mode 100644 index 0000000000..fede63e12b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "lockedstickers.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/lockedstickers.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/lockedstickers.pdf new file mode 100644 index 0000000000..554f3795b0 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/lockedstickers.pdf @@ -0,0 +1,93 @@ +%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 4.000000 2.999512 cm +0.000000 0.000000 0.000000 scn +2.165000 7.500039 m +2.165000 8.513481 2.986557 9.335039 4.000000 9.335039 c +5.013443 9.335039 5.835000 8.513481 5.835000 7.500039 c +5.835000 5.996800 l +5.637455 6.000156 5.413168 6.000156 5.155556 6.000156 c +2.844445 6.000156 l +2.586832 6.000156 2.362546 6.000156 2.165000 5.996800 c +2.165000 7.500039 l +h +0.835000 5.729585 m +0.835000 7.500039 l +0.835000 9.248020 2.252019 10.665039 4.000000 10.665039 c +5.747981 10.665039 7.165000 9.248020 7.165000 7.500039 c +7.165000 5.729585 l +7.437430 5.559180 7.659470 5.317513 7.806234 5.029473 c +8.000000 4.649185 8.000000 4.151361 8.000000 3.155712 c +8.000000 2.844601 l +8.000000 1.848951 8.000000 1.351128 7.806234 0.970840 c +7.635793 0.636330 7.363827 0.364364 7.029317 0.193922 c +6.649029 0.000156 6.151205 0.000156 5.155556 0.000156 c +2.844444 0.000156 l +1.848796 0.000156 1.350971 0.000156 0.970684 0.193922 c +0.636173 0.364364 0.364208 0.636330 0.193766 0.970840 c +0.000000 1.351128 0.000000 1.848951 0.000000 2.844601 c +0.000000 3.155712 l +0.000000 4.151361 0.000000 4.649185 0.193766 5.029473 c +0.340530 5.317513 0.562570 5.559180 0.835000 5.729585 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1229 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 16.000000 16.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 +0000001319 00000 n +0000001342 00000 n +0000001515 00000 n +0000001589 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1648 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json new file mode 100644 index 0000000000..5a3751c0b4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Group 1.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Group 1.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Group 1.svg new file mode 100644 index 0000000000..d93a88b5d0 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Group 1.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json new file mode 100644 index 0000000000..5d351b207e --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Frame 123.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Frame 123.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Frame 123.svg new file mode 100644 index 0000000000..64c31af2e3 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Frame 123.svg @@ -0,0 +1,4 @@ + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json new file mode 100644 index 0000000000..a16dd2f3bf --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "favourites_2455.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_2455.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_2455.svg new file mode 100644 index 0000000000..0a4622db25 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_2455.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Contents.json new file mode 100644 index 0000000000..d4c2fc76ea --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Locked.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Locked.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Locked.svg new file mode 100644 index 0000000000..b6181f185b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Locked.svg @@ -0,0 +1,4 @@ + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json new file mode 100644 index 0000000000..054e167a39 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "trendinggifs_24123.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24123.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24123.svg new file mode 100644 index 0000000000..4a56a4afc4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24123.svg @@ -0,0 +1,4 @@ + + + + diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Airplay.pdf b/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Airplay.pdf new file mode 100644 index 0000000000..756e9d0e9a --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Airplay.pdf @@ -0,0 +1,188 @@ +%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 2.335022 2.334961 cm +0.000000 0.000000 0.000000 scn +3.865000 17.330078 m +3.837526 17.330078 l +3.300828 17.330086 2.857980 17.330093 2.497252 17.300621 c +2.122623 17.270012 1.778399 17.204330 1.455116 17.039610 c +0.953664 16.784107 0.545970 16.376415 0.290468 15.874963 c +0.125747 15.551680 0.060066 15.207455 0.029457 14.832827 c +-0.000016 14.472098 -0.000009 14.029249 0.000000 13.492552 c +0.000000 13.465077 l +0.000000 7.865078 l +0.000000 7.837605 l +-0.000009 7.300907 -0.000016 6.858058 0.029457 6.497330 c +0.060066 6.122702 0.125747 5.778477 0.290468 5.455194 c +0.545970 4.953741 0.953664 4.546048 1.455116 4.290545 c +1.778399 4.125825 2.122623 4.060143 2.497252 4.029535 c +2.857977 4.000063 3.300821 4.000070 3.837511 4.000078 c +3.837541 4.000078 l +3.865000 4.000078 l +4.665000 4.000078 l +5.032270 4.000078 5.330000 4.297809 5.330000 4.665078 c +5.330000 5.032348 5.032270 5.330078 4.665000 5.330078 c +3.865000 5.330078 l +3.293975 5.330078 2.905699 5.330595 2.605556 5.355118 c +2.313176 5.379006 2.163463 5.422318 2.058923 5.475584 c +1.807727 5.603576 1.603498 5.807804 1.475507 6.059001 c +1.422241 6.163542 1.378929 6.313254 1.355040 6.605635 c +1.330518 6.905777 1.330000 7.294052 1.330000 7.865078 c +1.330000 13.465077 l +1.330000 14.036103 1.330518 14.424378 1.355040 14.724522 c +1.378929 15.016902 1.422241 15.166615 1.475507 15.271155 c +1.603498 15.522351 1.807727 15.726581 2.058923 15.854571 c +2.163463 15.907838 2.313176 15.951150 2.605556 15.975038 c +2.905699 15.999560 3.293974 16.000078 3.865000 16.000078 c +15.465000 16.000078 l +16.036026 16.000078 16.424301 15.999560 16.724445 15.975038 c +17.016823 15.951150 17.166538 15.907838 17.271076 15.854571 c +17.522274 15.726581 17.726501 15.522351 17.854492 15.271155 c +17.907761 15.166615 17.951073 15.016902 17.974960 14.724522 c +17.999481 14.424378 18.000000 14.036104 18.000000 13.465078 c +18.000000 7.865078 l +18.000000 7.294053 17.999481 6.905778 17.974960 6.605635 c +17.951073 6.313254 17.907761 6.163542 17.854492 6.059001 c +17.726501 5.807804 17.522274 5.603576 17.271076 5.475584 c +17.166538 5.422318 17.016823 5.379006 16.724445 5.355118 c +16.424301 5.330595 16.036026 5.330078 15.465000 5.330078 c +14.665000 5.330078 l +14.297730 5.330078 14.000000 5.032348 14.000000 4.665078 c +14.000000 4.297809 14.297730 4.000078 14.665000 4.000078 c +15.465000 4.000078 l +15.492459 4.000078 l +15.492488 4.000078 l +16.029179 4.000070 16.472023 4.000063 16.832748 4.029535 c +17.207378 4.060143 17.551601 4.125825 17.874886 4.290545 c +18.376335 4.546048 18.784031 4.953741 19.039532 5.455194 c +19.204254 5.778477 19.269936 6.122702 19.300545 6.497330 c +19.330015 6.858045 19.330009 7.300875 19.330002 7.837547 c +19.330002 7.837619 l +19.330002 7.865078 l +19.330002 13.465078 l +19.330002 13.492537 l +19.330002 13.492610 l +19.330009 14.029282 19.330015 14.472111 19.300545 14.832827 c +19.269936 15.207455 19.204254 15.551680 19.039532 15.874963 c +18.784031 16.376415 18.376335 16.784107 17.874886 17.039610 c +17.551601 17.204330 17.207378 17.270012 16.832748 17.300621 c +16.472019 17.330093 16.029171 17.330086 15.492474 17.330078 c +15.465000 17.330078 l +3.865000 17.330078 l +h +9.549997 5.417668 m +9.624264 5.444814 9.705738 5.444814 9.780005 5.417668 c +9.779352 5.417907 9.779119 5.418036 9.779340 5.417960 c +9.779449 5.417922 9.779672 5.417834 9.780010 5.417685 c +9.785703 5.415166 9.824282 5.395164 9.915651 5.303084 c +10.027624 5.190243 10.164604 5.026791 10.383287 4.764371 c +11.967221 2.863649 l +12.324518 2.434894 12.562548 2.148232 12.716402 1.925475 c +12.838650 1.748481 12.861221 1.674737 12.864748 1.663215 c +12.864949 1.662560 l +12.864219 1.564913 12.820898 1.472416 12.746351 1.409344 c +12.745722 1.409081 l +12.734627 1.404418 12.663531 1.374542 12.449274 1.355145 c +12.179653 1.330734 11.807049 1.330078 11.248934 1.330078 c +8.081068 1.330078 l +7.522953 1.330078 7.150349 1.330734 6.880728 1.355145 c +6.666473 1.374543 6.595378 1.404416 6.584280 1.409080 c +6.583652 1.409343 l +6.509105 1.472416 6.465783 1.564913 6.465053 1.662560 c +6.465254 1.663213 l +6.468780 1.674733 6.491349 1.748475 6.613600 1.925474 c +6.767454 2.148230 7.005483 2.434893 7.362779 2.863647 c +8.946714 4.764370 l +9.165398 5.026790 9.302377 5.190243 9.414351 5.303084 c +9.505718 5.395163 9.544298 5.415166 9.549992 5.417685 c +9.551012 5.418137 9.550975 5.418026 9.549997 5.417668 c +h +10.236588 6.666842 m +9.867472 6.801756 9.462530 6.801756 9.093414 6.666842 c +8.834289 6.572128 8.636753 6.407670 8.470269 6.239893 c +8.312561 6.080961 8.138463 5.872022 7.942029 5.636275 c +7.924980 5.615815 l +6.341045 3.715093 l +6.320368 3.690281 l +5.989172 3.292866 5.711553 2.959741 5.519254 2.681324 c +5.330824 2.408508 5.141049 2.075929 5.135232 1.690181 c +5.127517 1.178505 5.355523 0.691704 5.753542 0.370064 c +6.053606 0.127583 6.430592 0.060459 6.760806 0.030563 c +7.097775 0.000055 7.531381 0.000065 8.048665 0.000076 c +8.048759 0.000076 l +8.081068 0.000076 l +11.248934 0.000076 l +11.281242 0.000076 l +11.281337 0.000076 l +11.798622 0.000065 12.232226 0.000055 12.569197 0.030563 c +12.899410 0.060459 13.276397 0.127583 13.576460 0.370064 c +13.974480 0.691704 14.202486 1.178505 14.194770 1.690181 c +14.188953 2.075929 13.999178 2.408508 13.810747 2.681325 c +13.618445 2.959745 13.340822 3.292877 13.009618 3.690300 c +12.988955 3.715096 l +11.405022 5.615816 l +11.387974 5.636274 l +11.191540 5.872021 11.017441 6.080961 10.859733 6.239894 c +10.693249 6.407670 10.495712 6.572128 10.236588 6.666842 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 5505 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.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 +0000005595 00000 n +0000005618 00000 n +0000005791 00000 n +0000005865 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +5924 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Contents.json new file mode 100644 index 0000000000..458cfc4966 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Airplay.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Contents.json new file mode 100644 index 0000000000..95aadc5988 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Emoji (1).pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Emoji (1).pdf b/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Emoji (1).pdf new file mode 100644 index 0000000000..761a468d96 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Premium/Perk/Emoji.imageset/Emoji (1).pdf @@ -0,0 +1,120 @@ +%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 5.000000 5.000000 cm +1.000000 1.000000 1.000000 scn +0.000000 10.000000 m +0.000000 5.332758 3.197396 1.412308 7.521235 0.309603 c +7.192342 0.790955 7.000000 1.373016 7.000000 2.000000 c +7.000000 3.113091 l +5.212887 3.938812 4.297566 5.421120 3.859255 6.432051 c +3.686586 6.830300 4.118104 7.180214 4.520657 7.017826 c +5.607882 6.579245 7.514322 6.000000 10.000001 6.000000 c +12.485676 6.000000 14.392107 6.579244 15.479328 7.017824 c +15.881880 7.180212 16.313400 6.830300 16.140732 6.432050 c +15.702424 5.421119 14.787108 3.938814 13.000000 3.113092 c +13.000000 2.000000 l +13.000000 1.373016 12.807658 0.790955 12.478765 0.309603 c +16.802603 1.412308 20.000000 5.332758 20.000000 10.000000 c +20.000000 15.522848 15.522847 20.000000 10.000000 20.000000 c +4.477152 20.000000 0.000000 15.522848 0.000000 10.000000 c +h +14.000001 9.250000 m +15.242641 9.250000 16.250000 10.257360 16.250000 11.500000 c +16.250000 12.742640 15.242641 13.750000 14.000001 13.750000 c +12.757360 13.750000 11.750001 12.742640 11.750001 11.500000 c +11.750001 10.257360 12.757360 9.250000 14.000001 9.250000 c +h +14.000001 8.250000 m +15.794927 8.250000 17.250000 9.705074 17.250000 11.500000 c +17.250000 13.294926 15.794927 14.750000 14.000001 14.750000 c +12.205075 14.750000 10.750001 13.294926 10.750001 11.500000 c +10.750001 9.705074 12.205075 8.250000 14.000001 8.250000 c +h +15.000001 11.500000 m +15.000001 10.947716 14.552285 10.500000 14.000001 10.500000 c +13.447717 10.500000 13.000001 10.947716 13.000001 11.500000 c +13.000001 12.052284 13.447717 12.500000 14.000001 12.500000 c +14.552285 12.500000 15.000001 12.052284 15.000001 11.500000 c +h +8.982612 10.447145 m +8.552257 10.964127 7.794065 11.500000 6.500000 11.500000 c +5.205936 11.500000 4.447744 10.964127 4.017390 10.447145 c +3.744092 10.118834 4.103591 9.767232 4.509996 9.898819 c +5.063556 10.078053 5.781778 10.250000 6.500000 10.250000 c +7.218223 10.250000 7.936446 10.078053 8.490005 9.898819 c +8.896410 9.767232 9.255910 10.118834 8.982612 10.447145 c +h +9.000000 5.000000 m +8.447716 5.000000 8.000000 4.552284 8.000000 4.000000 c +8.000000 2.000000 l +8.000000 0.895432 8.895431 0.000000 10.000000 0.000000 c +11.104569 0.000000 12.000000 0.895432 12.000000 2.000000 c +12.000000 4.000000 l +12.000000 4.552284 11.552284 5.000000 11.000000 5.000000 c +10.714355 5.000000 10.473413 4.787300 10.437983 4.503861 c +10.137049 2.096386 l +10.116884 1.935076 9.883116 1.935074 9.862951 2.096386 c +9.562017 4.503861 l +9.526587 4.787299 9.285645 5.000000 9.000000 5.000000 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2574 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.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 +0000002664 00000 n +0000002687 00000 n +0000002860 00000 n +0000002934 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2993 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/anim_micToVideo.json b/submodules/TelegramUI/Resources/Animations/anim_micToVideo.json new file mode 100644 index 0000000000..fea54cbbc6 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/anim_micToVideo.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":30,"h":30,"nm":"micToVideo","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,25,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,2],[0,-2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[0]},{"t":14,"s":[25]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[100]},{"t":14,"s":[25]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 3","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.4,"y":0},"t":0,"s":[{"i":[[0.532,-1.104],[0,-2.884],[-0.63,-1.057],[-0.829,-0.535],[-2.458,0],[-0.793,0.482],[-0.351,0.627],[0,2.43],[0.536,1.112],[1.104,0.532],[2.884,0],[1.112,-0.536]],"o":[[-0.536,1.112],[0,1.993],[0.63,1.057],[0.829,0.535],[2.458,0],[0.793,-0.482],[0.351,-0.627],[0,-2.884],[-0.532,-1.104],[-1.112,-0.536],[-2.884,0],[-1.104,0.532]],"v":[[-7.964,-5.938],[-8.5,-0.5],[-7.205,4.052],[-4.586,6.672],[0,8],[4.614,6.672],[7.19,4.052],[8.5,-0.5],[7.964,-5.938],[5.438,-8.464],[0,-9],[-5.438,-8.464]],"c":true}]},{"t":14,"s":[{"i":[[0.688,-1.429],[0,-3.732],[-0.693,-1.439],[-1.429,-0.688],[-3.732,0],[-1.439,0.693],[-0.688,1.429],[0,3.732],[0.693,1.439],[1.429,0.688],[3.732,0],[1.439,-0.693]],"o":[[-0.693,1.439],[0,3.732],[0.688,1.429],[1.439,0.693],[3.732,0],[1.429,-0.688],[0.693,-1.439],[0,-3.732],[-0.688,-1.429],[-1.439,-0.693],[-3.732,0],[-1.429,0.688]],"v":[[-10.307,-7.037],[-11,0],[-10.307,7.037],[-7.037,10.307],[0,11],[7.037,10.307],[10.307,7.037],[11,0],[10.307,-7.037],[7.037,-10.307],[0,-11],[-7.037,-10.307]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[25.4]},{"t":14,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[74.7]},{"t":14,"s":[100]}],"ix":2},"o":{"a":0,"k":-59,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.4,"y":0},"t":0,"s":[{"i":[[2.485,0],[0,-2.485],[0,0],[-2.485,0],[0,2.485],[0,0]],"o":[[-2.485,0],[0,0],[0,2.485],[2.485,0],[0,0],[0,-2.485]],"v":[[0,-11],[-4.5,-6.5],[-4.5,-0.5],[0,4],[4.5,-0.5],[4.5,-6.5]],"c":true}]},{"t":14,"s":[{"i":[[2.761,0],[0,-2.761],[0,0],[-2.761,0],[0,2.761],[0,0]],"o":[[-2.761,0],[0,0],[0,2.761],[2.761,0],[0,0],[0,-2.761]],"v":[[0,-5],[-5,0],[-5,0.01],[0,5],[5,0.01],[5,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":5,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/anim_videoToMic.json b/submodules/TelegramUI/Resources/Animations/anim_videoToMic.json new file mode 100644 index 0000000000..5e150a4fdf --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/anim_videoToMic.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":30,"h":30,"nm":"videoToMic","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,25,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,2],[0,-2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[25]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[25]},{"t":12,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 3","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.4,"y":0},"t":0,"s":[{"i":[[0.688,-1.429],[0,-3.732],[-0.693,-1.439],[-1.429,-0.688],[-3.732,0],[-1.439,0.693],[-0.688,1.429],[0,3.732],[0.693,1.439],[1.429,0.688],[3.732,0],[1.439,-0.693]],"o":[[-0.693,1.439],[0,3.732],[0.688,1.429],[1.439,0.693],[3.732,0],[1.429,-0.688],[0.693,-1.439],[0,-3.732],[-0.688,-1.429],[-1.439,-0.693],[-3.732,0],[-1.429,0.688]],"v":[[-10.307,-7.037],[-11,0],[-10.307,7.037],[-7.037,10.307],[0,11],[7.037,10.307],[10.307,7.037],[11,0],[10.307,-7.037],[7.037,-10.307],[0,-11],[-7.037,-10.307]],"c":true}]},{"t":12,"s":[{"i":[[0.532,-1.104],[0,-2.884],[-0.63,-1.057],[-0.829,-0.535],[-2.458,0],[-0.793,0.482],[-0.351,0.627],[0,2.43],[0.536,1.112],[1.104,0.532],[2.884,0],[1.112,-0.536]],"o":[[-0.536,1.112],[0,1.993],[0.63,1.057],[0.829,0.535],[2.458,0],[0.793,-0.482],[0.351,-0.627],[0,-2.884],[-0.532,-1.104],[-1.112,-0.536],[-2.884,0],[-1.104,0.532]],"v":[[-7.964,-5.938],[-8.5,-0.5],[-7.205,4.052],[-4.586,6.672],[0,8],[4.614,6.672],[7.19,4.052],[8.5,-0.5],[7.964,-5.938],[5.438,-8.464],[0,-9],[-5.438,-8.464]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[25.4]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.4],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[74.7]}],"ix":2},"o":{"a":0,"k":-59,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Rectangle 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.4,"y":0},"t":0,"s":[{"i":[[2.761,0],[0,-2.761],[0,0],[-2.761,0],[0,2.761],[0,0]],"o":[[-2.761,0],[0,0],[0,2.761],[2.761,0],[0,0],[0,-2.761]],"v":[[0,-5],[-5,0],[-5,0.01],[0,5],[5,0.01],[5,0]],"c":true}]},{"t":12,"s":[{"i":[[2.485,0],[0,-2.485],[0,0],[-2.485,0],[0,2.485],[0,0]],"o":[[-2.485,0],[0,0],[0,2.485],[2.485,0],[0,0],[0,-2.485]],"v":[[0,-11],[-4.5,-6.5],[-4.5,-0.5],[0,4],[4.5,-0.5],[4.5,-6.5]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":5,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_activity.json b/submodules/TelegramUI/Resources/Animations/emojicat_activity.json new file mode 100644 index 0000000000..9c2695c402 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_activity.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"sport 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ellipse 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[15]},{"t":30,"s":[15]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[23.833]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[17.667]},{"t":30,"s":[15]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[6.667,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[16.667,13.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[16.667,16.667,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[16.667,15,100]},{"t":30,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[23,23],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector 65","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-0.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[4.5,-0.25],[0,-4.25],[-4.5,-0.25],[-2,4.25],[2,4.25]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 65","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector 68","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-34.5,46.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[1.252,-1],[3.75,-4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.75,-1],[1.252,-1]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.75,4],[1.252,-1]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 68","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Vector 67","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48,-19.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.5,1],[3.5,3]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.5,-4],[0.5,1]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.5,4],[0.5,1]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 67","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Vector 66","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.012,-43.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-0.5],[-0.002,3.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,-3.5],[0,-0.5]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-3.5],[0,-0.5]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 66","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Vector 68","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.5,46.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-1.25,-1],[-3.75,-4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.75,-1],[-1.25,-1]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3.75,4],[-1.25,-1]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 68","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Vector 67","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[48,-19.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.5,1],[-3.5,3]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.5,-4],[-0.5,1]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.5,4],[-0.5,1]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 67","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_animals.json b/submodules/TelegramUI/Resources/Animations/emojicat_animals.json new file mode 100644 index 0000000000..3c7276770d --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_animals.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"animals 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ellipse 43","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[38.217,-41.067,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[75,75,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[95,95,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-0.482,0.836],[2.152,1.243],[1.381,-2.391]],"o":[[0.751,-0.449],[1.381,-2.391],[-2.152,-1.243],[0,0]],"v":[[1.633,4.536],[3.53,2.595],[2.133,-3.986],[-4.264,-1.905]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 43","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Ellipse 42","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-38.201,-41.067,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[75,75,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[95,95,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0.482,0.836],[-2.152,1.243],[-1.381,-2.391]],"o":[[-0.751,-0.449],[-1.381,-2.391],[2.152,-1.243],[0,0]],"v":[[-1.633,4.536],[-3.53,2.595],[-2.133,-3.986],[4.264,-1.905]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 42","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse 41","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.001,-33,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[4.08,0],[0.492,-3.946]],"o":[[-0.492,-3.946],[-4.08,0],[0,0]],"v":[[7.938,3.5],[0,-3.5],[-7.938,3.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 41","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 40","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,51,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-9.3,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[-2.177,0],[-0.891,1.835]],"o":[[0.891,1.835],[2.177,0],[0,0]],"v":[[-4.95,-1.55],[0,1.55],[4.95,-1.55]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[0,0],[-2.177,0],[-0.891,1.835]],"o":[[0.891,1.835],[2.177,0],[0,0]],"v":[[-4.95,-1.55],[0,1.129],[4.95,-1.55]],"c":false}]},{"t":20,"s":[{"i":[[0,0],[-2.177,0],[-0.891,1.835]],"o":[[0.891,1.835],[2.177,0],[0,0]],"v":[[-4.95,-1.55],[0,1.55],[4.95,-1.55]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 40","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Ellipse 39","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[48,19.799,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.137],[3.038,0],[0,0]],"o":[[1.781,0.91],[0,3.038],[0,0],[0,0]],"v":[[0,-5.2],[3,-0.3],[-2.5,5.2],[-3,5.2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 39","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Ellipse 38","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-48,19.799,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.137],[-3.038,0],[0,0]],"o":[[-1.781,0.91],[0,3.038],[0,0],[0,0]],"v":[[0,-5.2],[-3,-0.3],[2.5,5.2],[3,5.2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 38","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Oval","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[27,1.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,30,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3,3.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Oval","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-27,1.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,30,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3,3.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Vector 64","parent":11,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.94],"y":[1]},"o":{"x":[0.06],"y":[0]},"t":0,"s":[-0.03]},{"i":{"x":[0.94],"y":[1]},"o":{"x":[0.06],"y":[0]},"t":10,"s":[-0.03]},{"t":20,"s":[-0.03]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[36.155]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[24.337]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[33.655]},{"t":30,"s":[31.155]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.507,0],[0,0],[0.38,-0.336],[0.152,-0.691],[0.113,0.516],[0.617,0.544]],"o":[[0,0],[0.507,0],[-0.617,0.544],[-0.112,0.511],[-0.152,-0.691],[-0.38,-0.336]],"v":[[-1.695,-1.693],[1.695,-1.693],[2.051,-0.619],[0.67,1.307],[-0.67,1.307],[-2.051,-0.619]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 64","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Vector","parent":9,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[0,9.345,0],"to":[0,-0.455,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[0,6.618,0],"to":[0,0,0],"ti":[0,-0.455,0]},{"t":20,"s":[0,9.345,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,0.75],[0,-1.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.552,0],[0,0.552]],"o":[[0,0],[0,0.552],[-0.552,0],[0,0]],"v":[[2,0.74],[2,0.75],[1,1.75],[0,0.75]],"c":false},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.552,0],[0,0.552]],"o":[[0,0],[0,0.552],[0.552,0],[0,0]],"v":[[-2,0.74],[-2,0.75],[-1,1.75],[0,0.75]],"c":false},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.33,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":3,"nm":"Ellipse 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[18.333,18.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_flags.json b/submodules/TelegramUI/Resources/Animations/emojicat_flags.json new file mode 100644 index 0000000000..670d52cc11 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_flags.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"flag 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 76","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[5]},{"t":20,"s":[0]}],"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[6]},{"t":20,"s":[6]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[9.333]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[17.833]},{"t":20,"s":[17]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[18.333,18.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,9],[0,-9]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":0,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 76","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 155","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[54,-33,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[4,0],[0,0],[0,0],[-4,0],[-4,0],[0,0],[0,0],[4,0]],"o":[[-4,0],[0,0],[0,0],[4,0],[4,0],[0,0],[0,0],[-4,0]],"v":[[-4,-4.417],[-9,-6.583],[-9,4.417],[-4,6.583],[4,4.417],[9,6.583],[9,-4.417],[4,-6.583]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[4,0],[0,0],[0,0],[-4,0],[-4,0],[0,0],[0,0],[4,0]],"o":[[-4,0],[0,0],[0,0],[4,0],[4,0],[0,0],[0,0],[-4,0]],"v":[[-4,-6.5],[-9,-4.5],[-9,6.5],[-4,4.5],[4,6.5],[9,4.5],[9,-6.5],[4,-4.5]],"c":true}]},{"t":30,"s":[{"i":[[4,0],[0,0],[0,0],[-4,0],[-4,0],[0,0],[0,0],[4,0]],"o":[[-4,0],[0,0],[0,0],[4,0],[4,0],[0,0],[0,0],[-4,0]],"v":[[-4,-4.417],[-9,-6.583],[-9,4.417],[-4,6.583],[4,4.417],[9,6.583],[9,-4.417],[4,-6.583]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 155","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_food.json b/submodules/TelegramUI/Resources/Animations/emojicat_food.json new file mode 100644 index 0000000000..27de3b30d3 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_food.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"food 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Rectangle 149","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[2.668,42.324,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.303,0.185],[0,0],[-0.03,0.119],[0.076,0.074],[0.508,0],[0,0],[0.088,-0.086],[-0.026,-0.103],[-0.434,-0.265],[0,0],[-0.162,-0.036],[-0.143,0.032]],"o":[[0,0],[0.434,-0.265],[0.026,-0.103],[-0.088,-0.086],[0,0],[-0.508,0],[-0.076,0.074],[0.03,0.119],[0,0],[0.303,0.185],[0.143,0.032],[0.162,-0.036]],"v":[[0.834,2.326],[7.544,-1.774],[8.225,-2.291],[8.144,-2.578],[7.294,-2.664],[-7.294,-2.664],[-8.144,-2.578],[-8.225,-2.291],[-7.544,-1.774],[-0.834,2.326],[-0.218,2.64],[0.218,2.64]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 149","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Rectangle 151","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[2.668,38.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":5,"s":[{"i":[[0,0],[0,0],[0,1.105],[-1.105,0],[0,0],[0,-1.105],[1.105,0],[0,0]],"o":[[0,0],[-1.105,0],[0,-1.105],[0,0],[1.105,0],[0,1.105],[0,0],[0,0]],"v":[[-3,2],[-7,2],[-9,0],[-7,-2],[7,-2],[9,0],[7,2],[3,2]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0,0],[0,0],[0,1.105],[-1.105,0],[0,0],[0,-1.105],[1.105,0],[0,0]],"o":[[0,0],[-1.105,0],[0,-1.105],[0,0],[1.105,0],[0,1.105],[0,0],[0,0]],"v":[[-3,1.667],[-9.5,1.667],[-11.5,0],[-9.5,-1.875],[9.5,-1.875],[11.5,0],[9.5,1.667],[3,1.667]],"c":false}]},{"t":25,"s":[{"i":[[0,0],[0,0],[0,1.105],[-1.105,0],[0,0],[0,-1.105],[1.105,0],[0,0]],"o":[[0,0],[-1.105,0],[0,-1.105],[0,0],[1.105,0],[0,1.105],[0,0],[0,0]],"v":[[-3,2],[-7,2],[-9,0],[-7,-2],[7,-2],[9,0],[7,2],[3,2]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 151","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Rectangle 150","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[2.668,62.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[110,110,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.214,-0.109],[-0.096,-0.188],[0,-0.56],[0,0],[0.109,-0.214],[0.188,-0.096],[0.56,0],[0,0],[0.214,0.109],[0.096,0.188],[0,0.56],[0,0],[-0.109,0.214],[-0.188,0.096],[-0.56,0],[0,0]],"o":[[0,0],[0.56,0],[0.188,0.096],[0.109,0.214],[0,0],[0,0.56],[-0.096,0.188],[-0.214,0.109],[0,0],[-0.56,0],[-0.188,-0.096],[-0.109,-0.214],[0,0],[0,-0.56],[0.096,-0.188],[0.214,-0.109],[0,0],[0,0]],"v":[[2.5,-2],[7.4,-2],[8.454,-1.891],[8.891,-1.454],[9,-0.4],[9,0.4],[8.891,1.454],[8.454,1.891],[7.4,2],[-7.4,2],[-8.454,1.891],[-8.891,1.454],[-9,0.4],[-9,-0.4],[-8.891,-1.454],[-8.454,-1.891],[-7.4,-2],[-2.5,-2]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":1,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 150","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-5,"op":65,"st":5,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Rectangle 148","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[2.668,8.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,1.667]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[110,110,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-6.517,0],[-0.495,-1.775],[0.978,0],[0,0],[-0.263,0.942]],"o":[[6.517,0],[0.262,0.942],[0,0],[-0.978,0],[0.495,-1.775]],"v":[[0,-3],[8.857,1.323],[7.306,3],[-7.306,3],[-8.857,1.323]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 148","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-4,"op":65,"st":5,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Vector 61","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-9.332,-43.299,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,-0.183]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[90,90,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.245,-0.041],[0.15,-0.159],[0.155,-0.568],[0,0]],"o":[[0,0],[-0.559,-0.186],[-0.216,0.036],[-0.17,0.181],[0,0],[0,0]],"v":[[3,-1.394],[0.105,-2.359],[-0.979,-2.597],[-1.542,-2.295],[-1.945,-1.262],[-3,2.606]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 61","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Rectangle 147","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-42.332,23.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.098,0.239],[0.199,0.11],[0.622,0],[0,0],[0.226,-0.125],[0.086,-0.21],[-0.073,-0.618],[0,0],[-0.116,-0.189],[-0.177,-0.082],[-0.503,0],[0,0]],"o":[[0,0],[0.073,-0.618],[-0.086,-0.21],[-0.226,-0.125],[0,0],[-0.622,0],[-0.199,0.11],[-0.098,0.239],[0,0],[0.059,0.5],[0.103,0.166],[0.201,0.094],[0,0],[0,0]],"v":[[5.147,-5.5],[5.29,-6.713],[5.301,-7.88],[4.86,-8.375],[3.701,-8.5],[-3.701,-8.5],[-4.86,-8.375],[-5.301,-7.88],[-5.29,-6.713],[-3.666,7.087],[-3.462,8.025],[-3.033,8.406],[-2.077,8.5],[-0.5,8.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":1,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 147","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[-9.332,14.34,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[18.333,18.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_objects.json b/submodules/TelegramUI/Resources/Animations/emojicat_objects.json new file mode 100644 index 0000000000..e45d5c6147 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_objects.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"lamp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Vector 72","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,45,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.5,0],[-3.5,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":0,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 72","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector 66","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.012,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[110,110,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-0.5],[-0.002,3.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-0.5],[-0.002,3.5]],"c":false}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-0.5],[-0.002,3.5]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-0.5],[-0.002,3.5]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,-3.5],[0,-0.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-3.5],[0,-0.5]],"c":false}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,-3.5],[0,-0.5]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-3.5],[0,-0.5]],"c":false}]}],"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-3.5],[0,-0.5]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":10,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,-3.5],[0,-0.5]],"c":false}]},{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-3.5],[0,-0.5]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-4,-3.5],[0,-0.5]],"c":false}]}],"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 66","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[-5]},{"t":30,"s":[0]}],"ix":10},"p":{"a":0,"k":[15,14.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[17.5,17.5,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.686,0.418],[0,3.257],[4.971,0],[0,-4.971],[-2.591,-1.58],[0,-0.804],[0,0],[-1.105,0],[0,0],[0,1.105],[0,0]],"o":[[2.591,-1.58],[0,-4.971],[-4.971,0],[0,3.257],[0.686,0.418],[0,0],[0,1.105],[0,0],[1.105,0],[0,0],[0,-0.804]],"v":[[4.679,5.19],[9,-2.5],[0,-11.5],[-9,-2.5],[-4.679,5.19],[-3.5,7.12],[-3.5,9.5],[-1.5,11.5],[1.5,11.5],[3.5,9.5],[3.5,7.12]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_places.json b/submodules/TelegramUI/Resources/Animations/emojicat_places.json new file mode 100644 index 0000000000..cd8eb3dcac --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_places.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"city 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 70","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[24,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-9,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[90,90,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.105,0],[0,1.105],[0,0]],"o":[[0,0],[0,1.105],[1.105,0],[0,0],[0,0]],"v":[[-2,-1.5],[-2,-0.5],[0,1.5],[2,-0.5],[2,-1.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 70","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector 69","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-24,18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-9,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[90,90,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-1.105,0],[0,1.105],[0,0]],"o":[[0,0],[0,1.105],[1.105,0],[0,0],[0,0]],"v":[[-2,-1.5],[-2,-0.5],[0,1.5],[2,-0.5],[2,-1.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 69","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse 46","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-18,0],"ix":2,"l":2},"a":{"a":0,"k":[0,16.5,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[90,90,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[3.038,0],[0,-3.038]],"o":[[0,-3.038],[-3.038,0],[0,0]],"v":[[5.5,2.75],[0,-2.75],[-5.5,2.75]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":2,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 46","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 45","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[24,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[150,150,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 45","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Ellipse 53","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[54,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[105,105,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 53","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Ellipse 51","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6,-21,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[105,105,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 51","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":10,"op":70,"st":10,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Ellipse 52","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[54,-3,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":2,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[105,105,100]},{"t":22,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":2,"op":62,"st":2,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Ellipse 49","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[6,-39,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":7,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":17,"s":[105,105,100]},{"t":27,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 49","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":7,"op":67,"st":7,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Ellipse 50","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18,-21,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":1,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":11,"s":[105,105,100]},{"t":21,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 50","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":61,"st":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Ellipse 48","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18,-39,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":9,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":19,"s":[105,105,100]},{"t":29,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 48","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":9,"op":69,"st":9,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Ellipse 47","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-54,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":4,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":14,"s":[105,105,100]},{"t":24,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 47","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":4,"op":64,"st":4,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Ellipse 44","parent":14,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-24,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[150,150,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2,2],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 44","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"Vector 71","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,22,0],"ix":2,"l":2},"a":{"a":0,"k":[0,57,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[17.5,17.5,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0.109,0.214],[0.188,0.096],[0.56,0],[0,0],[0.214,0.109],[0.096,0.188],[0,0.56],[0,0],[0.109,0.214],[0.188,0.096],[0.56,0],[0,0],[0.214,-0.109],[0.096,-0.188],[0,-0.56],[0,0],[0.109,-0.214],[0.188,-0.096],[0.56,0],[0,0],[0.214,-0.109],[0.096,-0.188],[0,-0.56],[0,0]],"o":[[0,0],[0,-0.56],[-0.096,-0.188],[-0.214,-0.109],[0,0],[-0.56,0],[-0.188,-0.096],[-0.109,-0.214],[0,0],[0,-0.56],[-0.096,-0.188],[-0.214,-0.109],[0,0],[-0.56,0],[-0.188,0.096],[-0.109,0.214],[0,0],[0,0.56],[-0.096,0.188],[-0.214,0.109],[0,0],[-0.56,0],[-0.188,0.096],[-0.109,0.214],[0,0],[0,0]],"v":[[12,9.5],[12,-1.9],[11.891,-2.954],[11.454,-3.391],[10.4,-3.5],[5.6,-3.5],[4.546,-3.609],[4.109,-4.046],[4,-5.1],[4,-7.9],[3.891,-8.954],[3.454,-9.391],[2.4,-9.5],[-4.4,-9.5],[-5.454,-9.391],[-5.891,-8.954],[-6,-7.9],[-6,-2.1],[-6.109,-1.046],[-6.546,-0.609],[-7.6,-0.5],[-10.4,-0.5],[-11.454,-0.391],[-11.891,0.046],[-12,1.1],[-12,9.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 71","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"Rectangle 153","parent":13,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,51,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[50,50,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[110,110,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.203,-0.49],[0,-0.932],[-0.152,-0.368],[-0.49,-0.203],[-0.932,0],[0,0],[-0.368,0.152],[-0.203,0.49],[0,0.932],[0.152,0.368],[0.49,0.203],[0.932,0],[0,0],[0.368,-0.152]],"o":[[-0.152,0.368],[0,0.932],[0.203,0.49],[0.368,0.152],[0,0],[0.932,0],[0.49,-0.203],[0.152,-0.368],[0,-0.932],[-0.203,-0.49],[-0.368,-0.152],[0,0],[-0.932,0],[-0.49,0.203]],"v":[[-7.848,-1.765],[-8,0],[-7.848,1.765],[-6.765,2.848],[-5,3],[5,3],[6.765,2.848],[7.848,1.765],[8,0],[7.848,-1.765],[6.765,-2.848],[5,-3],[-5,-3],[-6.765,-2.848]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 153","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_smiles.json b/submodules/TelegramUI/Resources/Animations/emojicat_smiles.json new file mode 100644 index 0000000000..58f8f55f0c --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_smiles.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"smiles 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Oval","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":21,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[-22.545]},{"t":20,"s":[-18]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,30,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3,3.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Oval","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":0,"k":-21,"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[-22.545]},{"t":20,"s":[-18]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,30,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[3,3.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Smileys & People","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"s":true,"x":{"a":1,"k":[{"i":{"x":[0.94],"y":[1]},"o":{"x":[0.06],"y":[0]},"t":0,"s":[-0.005]},{"i":{"x":[0.94],"y":[1]},"o":{"x":[0.06],"y":[0]},"t":10,"s":[-0.005]},{"t":20,"s":[-0.005]}],"ix":3},"y":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[35.413]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[25.867]},{"t":20,"s":[30.413]}],"ix":4}},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,95,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.366,-0.327],[2.153,0],[1.398,0.334],[0,-0.48],[-4.256,0],[0,4.256]],"o":[[-1.398,0.334],[-2.153,0],[-1.366,-0.327],[0,4.256],[4.256,0],[0,-0.48]],"v":[[5.498,-3.662],[0,-2.862],[-5.498,-3.662],[-7.706,-3.71],[0,3.996],[7.706,-3.71]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-2.045,0],[-1.076,0.282],[0,-0.307],[1.89,0],[0,2.95],[-0.895,-0.234]],"o":[[2.045,0],[0.895,-0.234],[0,2.949],[-1.683,0],[0,-0.307],[1.076,0.282]],"v":[[-0.009,-1.445],[4.762,-2.158],[6.156,-2.215],[-0.009,0.867],[-6.174,-2.215],[-4.781,-2.158]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[{"i":[[-2.045,0],[-1.076,0.282],[0,-0.307],[1.89,0],[0,2.95],[-0.895,-0.234]],"o":[[2.045,0],[0.895,-0.234],[0,2.949],[-1.683,0],[0,-0.307],[1.076,0.282]],"v":[[-0.009,-1.445],[4.762,-2.158],[6.156,-2.215],[-0.009,1.735],[-6.174,-2.215],[-4.781,-2.158]],"c":true}]},{"t":20,"s":[{"i":[[-2.045,0],[-1.076,0.282],[0,-0.307],[1.89,0],[0,2.95],[-0.895,-0.234]],"o":[[2.045,0],[0.895,-0.234],[0,2.949],[-1.683,0],[0,-0.307],[1.076,0.282]],"v":[[-0.009,-1.445],[4.762,-2.158],[6.156,-2.215],[-0.009,0.867],[-6.174,-2.215],[-4.781,-2.158]],"c":true}]}],"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Smileys & People","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[18.333,18.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[23,23],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/emojicat_symbols.json b/submodules/TelegramUI/Resources/Animations/emojicat_symbols.json new file mode 100644 index 0000000000..565bc14de9 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/emojicat_symbols.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":60,"w":30,"h":30,"nm":"symbols 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 75","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26.668,50.093,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[110,110,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.781,0],[0,0],[0.407,0.666],[0,0],[0.39,-0.638],[0,0]],"o":[[0,0],[0.781,0],[0,0],[-0.39,-0.638],[0,0],[-0.407,0.666]],"v":[[-3.717,4.041],[3.717,4.041],[4.57,2.52],[0.853,-3.563],[-0.853,-3.563],[-4.57,2.52]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":1,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 75","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector 74","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-45.332,50.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[110,110,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,-4],[-4,4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":2,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 74","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector 73","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-45.332,50.34,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[110,110,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[4,4],[-4,-4]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":2,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 73","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 54","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[26.668,-21.66,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":5,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[110,110,100]},{"t":25,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.485,0],[0,2.485],[2.485,0],[0,-2.485]],"o":[[2.485,0],[0,-2.485],[-2.485,0],[0,2.485]],"v":[[0,4.5],[4.5,0],[0,-4.5],[-4.5,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 54","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Rectangle 154","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-45.332,-21.66,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[110,110,100]},{"t":30,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.192,-0.376],[0,-1.12],[0,0],[-0.218,-0.428],[-0.376,-0.192],[-1.12,0],[0,0],[-0.428,0.218],[-0.192,0.376],[0,1.12],[0,0],[0.218,0.428],[0.376,0.192],[1.12,0],[0,0],[0.428,-0.218]],"o":[[-0.218,0.428],[0,0],[0,1.12],[0.192,0.376],[0.428,0.218],[0,0],[1.12,0],[0.376,-0.192],[0.218,-0.428],[0,0],[0,-1.12],[-0.192,-0.376],[-0.428,-0.218],[0,0],[-1.12,0],[-0.376,0.192]],"v":[[-3.782,-2.908],[-4,-0.8],[-4,0.8],[-3.782,2.908],[-2.908,3.782],[-0.8,4],[0.8,4],[2.908,3.782],[3.782,2.908],[4,0.8],[4,-0.8],[3.782,-2.908],[2.908,-3.782],[0.8,-4],[-0.8,-4],[-2.908,-3.782]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 154","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[-90]},{"t":10,"s":[0]}],"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[-9.332,14.34,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[8.333,8.333,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[18.333,18.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":60,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_botToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_botToKey.json new file mode 100644 index 0000000000..d08ff0f116 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_botToKey.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":320,"h":320,"nm":"bot_to_keyboard","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ellipse 27","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[191.15,191.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":13,"s":[191.15,191.15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]},{"t":13,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-0.1,-4.435],[1.235,-3.1],[-0.1,-1.765],[-1.435,-3.1]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":13,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[1.33]},{"t":13,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 27","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Ellipse 25","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[191.15,127.85,0],"to":[0,0,0],"ti":[0,0,0]},{"t":13,"s":[191.15,127.85,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]},{"t":13,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-0.1,-2.135],[1.235,-0.8],[-0.1,0.535],[-1.435,-0.8]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[1.33]},{"t":13,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":13,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 25","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse 26","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[127.85,191.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":13,"s":[127.85,191.15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]},{"t":13,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-5.775,-4.435],[-4.44,-3.1],[-5.775,-1.765],[-7.11,-3.1]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[1.33]},{"t":13,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":13,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 26","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 24","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[127.85,127.85,0],"to":[0,0,0],"ti":[0,0,0]},{"t":13,"s":[127.85,127.85,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]},{"t":13,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-5.775,-2.11],[-4.44,-0.775],[-5.775,0.56],[-7.11,-0.775]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[1.33]},{"t":13,"s":[0]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":13,"s":[100]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 24","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Union","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":3,"s":[0]},{"t":13,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[156.051,159.049,0],"to":[-4.333,-4.333,0],"ti":[4.333,4.333,0]},{"t":13,"s":[130.051,140.049,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":1,"s":[50,50,100]},{"t":13,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Vector","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[1]},{"t":13,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[130,210,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[7.4,2],[2.889,2],[-1.6,2]],"c":false}]},{"t":13,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[4.5,0],[-0.011,0],[-4.5,0]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[50]},{"t":13,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[50]},{"t":13,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":13,"s":[1.66]}],"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,160,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0.479,-0.941],[0,-2.8],[0,0],[-0.545,-1.07],[-0.941,-0.479],[-2.8,0],[0,0],[-1.07,0.545],[-0.479,0.941],[0,2.8],[0,0],[0.545,1.07],[0.941,0.479],[2.8,0],[0,0],[1.07,-0.545]],"o":[[-0.545,1.07],[0,0],[0,2.8],[0.479,0.941],[1.07,0.545],[0,0],[2.8,0],[0.941,-0.479],[0.545,-1.07],[0,0],[0,-2.8],[-0.479,-0.941],[-1.07,-0.545],[0,0],[-2.8,0],[-0.941,0.479]],"v":[[-8.62,-6.435],[-9.165,-1.165],[-9.165,1.165],[-8.62,6.435],[-6.435,8.62],[-1.165,9.165],[1.165,9.165],[6.435,8.62],[8.62,6.435],[9.165,1.165],[9.165,-1.165],[8.62,-6.435],[6.435,-8.62],[1.165,-9.165],[-1.165,-9.165],[-6.435,-8.62]],"c":true}],"h":1},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":1,"s":[{"i":[[0.246,-0.594],[0.086,-1.097],[0,-1.5],[-0.086,-1.12],[-0.229,-0.551],[-0.686,-0.284],[-2.796,0],[0,0],[-1.103,0.457],[-0.284,0.686],[0,3],[0.457,1.103],[0.845,0.35],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.229,0.551],[-0.086,1.097],[0,1.398],[0.086,1.12],[0.377,0.911],[1.103,0.457],[0,0],[2.796,0],[0.938,-0.388],[0.457,-1.103],[0,-3],[-0.294,-0.71],[-1.103,-0.457],[0,0],[-2.796,0],[-1.103,0.457]],"v":[[-8.63,-6.44],[-9.088,-3.931],[-9.204,0],[-9.088,3.85],[-8.63,6.43],[-6.44,8.62],[-1.204,9.204],[1.204,9.204],[6.43,8.62],[8.62,6.43],[9.204,0],[8.62,-6.44],[6.43,-8.63],[1.204,-9.204],[-1.204,-9.204],[-6.44,-8.63]],"c":true}]},{"t":13,"s":[{"i":[[0.609,-1.47],[0.057,-0.837],[0,-1.398],[-0.057,-0.837],[-0.229,-0.551],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.229,0.551],[-0.057,0.837],[0,1.398],[0.057,0.837],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-14.943,-3.283],[-15,0],[-14.943,3.283],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_channelMute.json b/submodules/TelegramUI/Resources/Animations/input_anim_channelMute.json new file mode 100644 index 0000000000..5ef523d12f --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_channelMute.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":40,"w":32,"h":32,"nm":"mute","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Vector 186","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[20,-16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.75,8],[-7.75,-8]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":3,"s":[100]},{"t":17,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 186","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Intersect","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.031,136,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.307,0],[-0.412,1.165],[0,0]],"o":[[1.307,0],[0,0],[0.412,1.165]],"v":[[0,1],[2.831,-1],[-2.831,-1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Intersect","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Rectangle 47 (Stroke)","parent":4,"sr":1,"ks":{"o":{"a":0,"k":94,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.001,-26.64,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.316,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.316,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[-104.699,-79.295],[-74.1,-78.809],[-73.615,-109.405],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.315,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.316,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[-75.175,-50.24],[-44.576,-49.754],[-44.09,-80.35],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.315,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.315,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[74.367,101.634],[104.966,102.119],[105.452,71.524],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.131,0],[0,-3.131],[0,0],[0.357,-0.782],[0,0],[-0.91,0],[0,0],[0.378,0.828],[0,0],[0,0.859],[0,0]],"o":[[-3.131,0],[0,0],[0,0.859],[0,0],[-0.378,0.828],[0,0],[0.91,0],[0,0],[-0.357,-0.782],[0,0],[0,-3.131]],"v":[[0,-7],[-5.67,-1.33],[-5.67,-0.134],[-6.211,2.356],[-7.523,5.231],[-6.386,7],[6.386,7],[7.523,5.231],[6.211,2.356],[5.67,-0.134],[5.67,-1.33]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 47 (Stroke)","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Top 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":2,"s":[0]},{"i":{"x":[0.302],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":8,"s":[-3]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":19,"s":[5]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":28,"s":[-3]},{"t":36,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[15.943,16.313,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":6,"s":[15.943,15.063,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":17,"s":[15.943,17.563,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":26,"s":[15.943,15.438,0],"to":[0,0,0],"ti":[0,0,0]},{"t":34,"s":[15.943,16.313,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.918,5,0],"ix":1,"l":2},"s":{"a":0,"k":[6.25,6.25,100],"ix":6,"l":2}},"ao":0,"ip":5,"op":40,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_channelUnmute.json b/submodules/TelegramUI/Resources/Animations/input_anim_channelUnmute.json new file mode 100644 index 0000000000..7000a1a973 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_channelUnmute.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":40,"w":32,"h":32,"nm":"unmute","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Top 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":7,"s":[3]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":20,"s":[-5]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":29,"s":[3]},{"t":36,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[15.943,16.313,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":5,"s":[15.943,17.563,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":18,"s":[15.943,14.813,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":27,"s":[15.943,17.688,0],"to":[0,0,0],"ti":[0,0,0]},{"t":34,"s":[15.943,16.313,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.918,5,0],"ix":1,"l":2},"s":{"a":0,"k":[6.25,6.25,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":13,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector 186","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[20,-16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[7.75,8],[-7.75,-8]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":3,"s":[0]},{"t":17,"s":[100]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 186","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Intersect","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.031,136,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.307,0],[-0.412,1.165],[0,0]],"o":[[1.307,0],[0,0],[0.412,1.165]],"v":[[0,1],[2.831,-1],[-2.831,-1]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Intersect","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Rectangle 47 (Stroke)","parent":1,"sr":1,"ks":{"o":{"a":0,"k":94,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.001,-26.64,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[160,160,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.315,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.315,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[74.367,101.634],[104.966,102.119],[105.452,71.524],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.315,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.316,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[-75.175,-50.24],[-44.576,-49.754],[-44.09,-80.35],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[-8.584,8.315],[8.316,8.583],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[8.316,8.583],[8.584,-8.315],[0,0],[0,0],[0,0],[0,0]],"v":[[-159.968,176.525],[-159.968,-141.599],[-104.699,-79.295],[-74.1,-78.809],[-73.615,-109.405],[-101.502,-143.288],[159.875,-143.288],[159.875,176.525]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[3.131,0],[0,-3.131],[0,0],[0.357,-0.782],[0,0],[-0.91,0],[0,0],[0.378,0.828],[0,0],[0,0.859],[0,0]],"o":[[-3.131,0],[0,0],[0,0.859],[0,0],[-0.378,0.828],[0,0],[0.91,0],[0,0],[-0.357,-0.782],[0,0],[0,-3.131]],"v":[[0,-7],[-5.67,-1.33],[-5.67,-0.134],[-6.211,2.356],[-7.523,5.231],[-6.386,7],[6.386,7],[7.523,5.231],[6.211,2.356],[5.67,-0.134],[5.67,-1.33]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 47 (Stroke)","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":40,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_keyToBot.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToBot.json new file mode 100644 index 0000000000..0037c39c0d --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_keyToBot.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":320,"h":320,"nm":"keyboard_to_bot","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Ellipse 27","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":0,"s":[191.15,191.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[191.15,191.15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-0.1,-4.435],[1.235,-3.1],[-0.1,-1.765],[-1.435,-3.1]],"c":true}]},{"t":12,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[1.33]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 27","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Ellipse 25","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":0,"s":[191.15,127.85,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[191.15,127.85,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-0.1,-2.135],[1.235,-0.8],[-0.1,0.535],[-1.435,-0.8]],"c":true}]},{"t":12,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[1.33]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 25","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Ellipse 26","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":0,"s":[127.85,191.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[127.85,191.15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-5.775,-4.435],[-4.44,-3.1],[-5.775,-1.765],[-7.11,-3.1]],"c":true}]},{"t":12,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[1.33]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 26","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 24","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":0,"s":[127.85,127.85,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[127.85,127.85,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-5.775,-2.11],[-4.44,-0.775],[-5.775,0.56],[-7.11,-0.775]],"c":true}]},{"t":12,"s":[{"i":[[-1.031,0],[0,-1.031],[1.031,0],[0,1.031]],"o":[[1.031,0],[0,1.031],[-1.031,0],[0,-1.031]],"v":[[0,-1.835],[1.835,0],[0,1.835],[-1.835,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[1.33]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 24","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Union","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":9,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[130.051,140.049,0],"to":[-4.333,-4.333,0],"ti":[4.333,4.333,0]},{"t":12,"s":[156.051,159.049,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"t":12,"s":[50,50,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Vector","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[1]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[130,210,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[4.5,0],[-0.011,0],[-4.5,0]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[7.4,2],[2.889,2],[-1.6,2]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[50]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[1.66]},{"t":12,"s":[0]}],"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[160,160,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0.609,-1.47],[0.057,-0.837],[0,-1.398],[-0.057,-0.837],[-0.229,-0.551],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.229,0.551],[-0.057,0.837],[0,1.398],[0.057,0.837],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-14.943,-3.283],[-15,0],[-14.943,3.283],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]},{"t":12,"s":[{"i":[[0.246,-0.594],[0.086,-1.097],[0,-1.5],[-0.086,-1.12],[-0.229,-0.551],[-0.686,-0.284],[-2.796,0],[0,0],[-1.103,0.457],[-0.284,0.686],[0,3],[0.457,1.103],[0.845,0.35],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.229,0.551],[-0.086,1.097],[0,1.398],[0.086,1.12],[0.377,0.911],[1.103,0.457],[0,0],[2.796,0],[0.938,-0.388],[0.457,-1.103],[0,-3],[-0.294,-0.71],[-1.103,-0.457],[0,0],[-2.796,0],[-1.103,0.457]],"v":[[-8.63,-6.44],[-9.088,-3.931],[-9.204,0],[-9.088,3.85],[-8.63,6.43],[-6.44,8.62],[-1.204,9.204],[1.204,9.204],[6.43,8.62],[8.62,6.43],[9.204,0],[8.62,-6.44],[6.43,-8.63],[1.204,-9.204],[-1.204,-9.204],[-6.44,-8.63]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0.479,-0.941],[0,-2.8],[0,0],[-0.545,-1.07],[-0.941,-0.479],[-2.8,0],[0,0],[-1.07,0.545],[-0.479,0.941],[0,2.8],[0,0],[0.545,1.07],[0.941,0.479],[2.8,0],[0,0],[1.07,-0.545]],"o":[[-0.545,1.07],[0,0],[0,2.8],[0.479,0.941],[1.07,0.545],[0,0],[2.8,0],[0.941,-0.479],[0.545,-1.07],[0,0],[0,-2.8],[-0.479,-0.941],[-1.07,-0.545],[0,0],[-2.8,0],[-0.941,0.479]],"v":[[-8.62,-6.435],[-9.165,-1.165],[-9.165,1.165],[-8.62,6.435],[-6.435,8.62],[-1.165,9.165],[1.165,9.165],[6.435,8.62],[8.62,6.435],[9.165,1.165],[9.165,-1.165],[8.62,-6.435],[6.435,-8.62],[1.165,-9.165],[-1.165,-9.165],[-6.435,-8.62]],"c":true}],"h":1}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_keyToSmile.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSmile.json new file mode 100644 index 0000000000..644e916a01 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSmile.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":32,"h":32,"nm":"keyboard_to_smile","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"keys","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[13.005,14.005,0],"to":[-0.517,-0.25,0],"ti":[0.517,0.25,0]},{"t":12,"s":[16.105,15.505,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[10,10,100]},{"t":12,"s":[5,5,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,0.665],[7.335,2],[6,3.335],[4.665,2]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,0.665],[-4.665,2],[-6,3.335],[-7.335,2]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":8,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Reye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.174,14.152,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0.737],[0.737,0],[0,-0.737],[-0.737,0]],"o":[[0,-0.737],[-0.737,0],[0,0.737],[0.737,0]],"v":[[1.167,-2.149],[-0.168,-3.484],[-1.503,-2.149],[-0.168,-0.814]],"c":true}]},{"t":12,"s":[{"i":[[0,0.756],[0.648,0],[0,-0.756],[-0.648,0]],"o":[[0,-0.756],[-0.648,0],[0,0.756],[0.648,0]],"v":[[1.174,0],[0,-1.37],[-1.174,0],[0,1.37]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Leye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12.834,14.152,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0.737],[0.737,0],[0,-0.737],[-0.737,0]],"o":[[0,-0.737],[-0.737,0],[0,0.737],[0.737,0]],"v":[[-4.494,-2.148],[-5.829,-3.483],[-7.164,-2.148],[-5.829,-0.813]],"c":true}]},{"t":12,"s":[{"i":[[0,0.756],[0.648,0],[0,-0.756],[-0.648,0]],"o":[[0,-0.756],[-0.648,0],[0,0.756],[0.648,0]],"v":[[1.174,0],[0,-1.37],[-1.174,0],[0,1.37]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"smile","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,19.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[1.5,1.462],[-3.011,1.462],[-7.5,1.462]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[3.5,-0.965],[0,0.965],[-3.5,-0.965]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0.609,-1.47],[0,-2.796],[-0.457,-1.103],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.457,1.103],[0,2.796],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-15,0],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]},{"t":12,"s":[{"i":[[0.563,-1.25],[0,-1.781],[-0.829,-1.478],[-1.041,-0.505],[-2.097,0],[0,0],[-0.827,0.457],[-0.749,1.289],[0,2.003],[0.491,0.934],[1.305,0.721],[2.291,0],[0,0],[1.002,-0.754]],"o":[[-0.563,1.25],[0,1.718],[0.829,1.478],[1.041,0.505],[0,0],[2.097,0],[1.229,-0.632],[0.749,-1.289],[0,-2.063],[-0.491,-0.934],[-1.305,-0.721],[0,0],[-2.296,0],[-1.002,0.754]],"v":[[-8.024,-4.097],[-9,0],[-7.751,4.589],[-4.228,7.953],[0,9],[0.01,9],[4.362,7.874],[7.688,4.693],[9,0],[7.887,-4.367],[4.783,-7.619],[0.01,-9],[0,-9],[-5.348,-7.242]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_keyToSticker.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSticker.json new file mode 100644 index 0000000000..6e4c44cd25 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSticker.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":32,"h":32,"nm":"keyboard_to_sticker","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Union","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":9,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[13.005,14.005,0],"to":[-0.433,-0.433,0],"ti":[0.433,0.433,0]},{"t":12,"s":[15.605,16.605,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[10,10,100]},{"t":12,"s":[5,5,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,-3.335],[7.335,-2],[6,-0.665],[4.665,-2]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,0.665],[7.335,2],[6,3.335],[4.665,2]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,-3.335],[-4.665,-2],[-6,-0.665],[-7.335,-2]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,0.665],[-4.665,2],[-6,3.335],[-7.335,2]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":10,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":9,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.051,69.951,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[4.5,0],[-0.011,0],[-4.5,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18.035,13.965,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[6.107,-14.743],[0,-28.034],[-4.58,-11.057],[-14.743,-6.107],[-28.034,0],[0,0],[-11.057,4.58],[-6.107,14.743],[0,28.034],[4.58,11.057],[14.743,6.107],[28.034,0],[0,0],[11.057,-4.58]],"o":[[-4.58,11.057],[0,28.034],[6.107,14.743],[11.057,4.58],[0,0],[28.034,0],[14.743,-6.107],[4.58,-11.057],[0,-28.034],[-6.107,-14.743],[-11.057,-4.58],[0,0],[-28.034,0],[-14.743,6.107]],"v":[[-165.437,-33.008],[-170.017,20.1],[-165.437,73.208],[-132.875,105.77],[-79.767,110.35],[-19.6,110.35],[33.508,105.77],[66.07,73.208],[70.65,20.1],[66.07,-33.008],[33.508,-65.57],[-19.6,-70.15],[-79.767,-70.15],[-132.875,-65.57]],"c":true}]},{"t":12,"s":[{"i":[[5.686,-12.682],[0,-18.058],[-8.379,-14.991],[-10.518,-5.125],[-21.187,0],[0,0],[-8.356,4.632],[-7.57,13.076],[0,5.926],[19.097,19.964],[0,0],[13.777,0],[0,0],[10.126,-7.646]],"o":[[-5.686,12.682],[0,17.428],[8.379,14.991],[10.518,5.125],[0,0],[21.187,0],[12.419,-6.413],[7.57,-13.076],[0,-11.57],[0,0],[-19.906,-19.168],[0,0],[-15.925,0],[-10.126,7.646]],"v":[[-101.485,-20.984],[-111.35,20.572],[-98.733,67.109],[-63.133,101.229],[-20.41,111.85],[-20.308,111.85],[23.665,100.43],[57.273,68.164],[65.15,41.804],[40.217,-9.838],[9.904,-40.28],[-41.128,-65.15],[-41.229,-65.15],[-74.451,-52.874]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,-0.929],[0,0],[-4.447,0],[0,0],[0.409,-0.834],[0,0]],"o":[[0,0],[0.834,-0.409],[0,0],[0,4.447],[0,0],[0.929,0],[0,0],[0,0]],"v":[[1.335,-12.935],[1.54,-13.035],[3.348,-11.908],[3.348,-10.901],[11.401,-2.848],[12.408,-2.848],[13.535,-1.04],[13.435,-0.835]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[0,0],[0,-0.929],[0,0],[-4.447,0],[0,0],[0.409,-0.834],[0,0]],"o":[[0,0],[0.834,-0.409],[0,0],[0,4.447],[0,0],[0.929,0],[0,0],[0,0]],"v":[[-6.415,-5.735],[-6.21,-5.835],[-4.402,-4.708],[-4.402,-3.701],[3.651,4.352],[4.658,4.352],[5.785,6.16],[5.685,6.365]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0.609,-1.47],[0,-2.796],[-0.457,-1.103],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.457,1.103],[0,2.796],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-15,0],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]},{"t":12,"s":[{"i":[[0.563,-1.25],[0,-1.781],[-0.829,-1.478],[-1.041,-0.505],[-2.097,0],[0,0],[-0.827,0.457],[-0.749,1.289],[0,0.584],[1.89,1.968],[0,0],[1.363,0],[0,0],[1.002,-0.754]],"o":[[-0.563,1.25],[0,1.718],[0.829,1.478],[1.041,0.505],[0,0],[2.097,0],[1.229,-0.632],[0.749,-1.289],[0,-1.141],[0,0],[-1.97,-1.89],[0,0],[-1.576,0],[-1.002,0.754]],"v":[[-8.007,-4.096],[-8.984,0.001],[-7.735,4.59],[-4.212,7.954],[0.016,9.001],[0.026,9.001],[4.378,7.875],[7.704,4.694],[8.484,2.095],[6.016,-2.997],[3.016,-5.999],[-2.034,-8.451],[-2.044,-8.451],[-5.332,-7.241]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_smileToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_smileToKey.json new file mode 100644 index 0000000000..3197e866b1 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_smileToKey.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":32,"h":32,"nm":"smile_to_keyboard","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"keys","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[16.105,15.505,0],"to":[-0.517,-0.25,0],"ti":[0.517,0.25,0]},{"t":12,"s":[13.005,14.005,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[5,5,100]},{"t":12,"s":[10,10,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,0.665],[7.335,2],[6,3.335],[4.665,2]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,0.665],[-4.665,2],[-6,3.335],[-7.335,2]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":8,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Reye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.174,14.152,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0.756],[0.648,0],[0,-0.756],[-0.648,0]],"o":[[0,-0.756],[-0.648,0],[0,0.756],[0.648,0]],"v":[[1.174,0],[0,-1.37],[-1.174,0],[0,1.37]],"c":true}]},{"t":12,"s":[{"i":[[0,0.737],[0.737,0],[0,-0.737],[-0.737,0]],"o":[[0,-0.737],[-0.737,0],[0,0.737],[0.737,0]],"v":[[1.167,-2.149],[-0.168,-3.484],[-1.503,-2.149],[-0.168,-0.814]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Leye","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12.834,14.152,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0.756],[0.648,0],[0,-0.756],[-0.648,0]],"o":[[0,-0.756],[-0.648,0],[0,0.756],[0.648,0]],"v":[[1.174,0],[0,-1.37],[-1.174,0],[0,1.37]],"c":true}]},{"t":12,"s":[{"i":[[0,0.737],[0.737,0],[0,-0.737],[-0.737,0]],"o":[[0,-0.737],[-0.737,0],[0,0.737],[0.737,0]],"v":[[-4.494,-2.148],[-5.829,-3.483],[-7.164,-2.148],[-5.829,-0.813]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"smile","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,19.536,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[3.5,-0.965],[0,0.965],[-3.5,-0.965]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[1.5,1.462],[-3.011,1.462],[-7.5,1.462]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0.563,-1.25],[0,-1.781],[-0.829,-1.478],[-1.041,-0.505],[-2.097,0],[0,0],[-0.827,0.457],[-0.749,1.289],[0,2.003],[0.491,0.934],[1.305,0.721],[2.291,0],[0,0],[1.002,-0.754]],"o":[[-0.563,1.25],[0,1.718],[0.829,1.478],[1.041,0.505],[0,0],[2.097,0],[1.229,-0.632],[0.749,-1.289],[0,-2.063],[-0.491,-0.934],[-1.305,-0.721],[0,0],[-2.296,0],[-1.002,0.754]],"v":[[-8.024,-4.097],[-9,0],[-7.751,4.589],[-4.228,7.953],[0,9],[0.01,9],[4.362,7.874],[7.688,4.693],[9,0],[7.887,-4.367],[4.783,-7.619],[0.01,-9],[0,-9],[-5.348,-7.242]],"c":true}]},{"t":12,"s":[{"i":[[0.609,-1.47],[0,-2.796],[-0.457,-1.103],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.457,1.103],[0,2.796],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-15,0],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_smileToSticker.json b/submodules/TelegramUI/Resources/Animations/input_anim_smileToSticker.json new file mode 100644 index 0000000000..26d136207a --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_smileToSticker.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":24,"w":30,"h":30,"nm":"smiletosticker","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path 85","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12.746,-12.746,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[5,0],[0,0],[0.829,-0.406],[0,0]],"o":[[0,0],[0.406,-0.829],[0,-0.391],[0,-5],[-0.391,0],[0,0],[-0.829,0.406],[0,0]],"v":[[5.633,6.5],[5.733,6.296],[6.613,4.5],[6.613,2.5],[-2.387,-6.5],[-4.387,-6.5],[-6.183,-5.62],[-6.387,-5.52]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0.923,0],[0,0],[0,4.418],[0,0],[0.829,-0.406],[0,0]],"o":[[0,0],[0.406,-0.829],[0,0],[-4.418,0],[0,0],[0,-0.923],[0,0],[0,0]],"v":[[5.896,6.124],[5.996,5.92],[4.876,4.124],[3.467,4.124],[-4.124,-3.467],[-4.124,-4.876],[-5.92,-5.996],[-6.124,-5.896]],"c":false}]},{"t":20,"s":[{"i":[[0,0],[0,0],[0.923,0],[0,0],[0,4.418],[0,0],[0.829,-0.406],[0,0]],"o":[[0,0],[0.406,-0.829],[0,0],[-4.418,0],[0,0],[0,-0.923],[0,0],[0,0]],"v":[[5.896,6.124],[5.996,5.92],[4.876,4.124],[3.876,4.124],[-4.124,-3.876],[-4.124,-4.876],[-5.92,-5.996],[-6.124,-5.896]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 85","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":2,"op":24,"st":-60,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Oval 2","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.043,-11.087,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"t":5,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2.348,2.739],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":24,"st":-60,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.997,-11.087,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"t":5,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2.348,2.739],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":24,"st":-60,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Ellipse 34","parent":5,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,21.212,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.363,0],[0,0]],"o":[[0,0],[2.363,0],[0,0]],"v":[[-3.5,-0.965],[0,0.965],[3.5,-0.965]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 34","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":5,"s":[50]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":5,"s":[50]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":24,"st":-60,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Ellipse 33","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[15,15,0],"to":[-0.045,0.043,0],"ti":[0.045,-0.043,0]},{"t":10,"s":[14.728,15.259,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[-4.971,0],[0,4.971],[0.599,1.205],[1.758,0.874],[1.437,0],[0,-4.971]],"o":[[4.971,0],[0,-1.437],[-0.874,-1.758],[-1.205,-0.599],[-4.971,0],[0,4.971]],"v":[[0,9],[9,0],[8.064,-4],[4,-8.064],[0,-9],[-9,0]],"c":true}]},{"t":10,"s":[{"i":[[-4.971,0],[-1.46,2.97],[1.89,1.97],[0,0],[2.35,-1.126],[0,-3.49]],"o":[[3.49,0],[1.19,-2.35],[0,0],[-1.97,-1.89],[-2.97,1.524],[0,4.971]],"v":[[0.272,8.741],[8.272,3.741],[6.272,-3.259],[3.272,-6.259],[-3.728,-8.323],[-8.728,-0.259]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 33","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":24,"st":-60,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_stickerToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToKey.json new file mode 100644 index 0000000000..ce92cd33da --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToKey.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":15,"w":32,"h":32,"nm":"sticker_to_keyboard","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Union","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":3,"s":[0]},{"t":12,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[15.605,16.605,0],"to":[-0.433,-0.433,0],"ti":[0.433,0.433,0]},{"t":12,"s":[13.005,14.005,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":0,"s":[5,5,100]},{"t":12,"s":[10,10,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,-3.335],[7.335,-2],[6,-0.665],[4.665,-2]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[6,0.665],[7.335,2],[6,3.335],[4.665,2]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,-3.335],[3.335,-2],[2,-0.665],[0.665,-2]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[2,0.665],[3.335,2],[2,3.335],[0.665,2]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,-3.335],[-0.665,-2],[-2,-0.665],[-3.335,-2]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-2,0.665],[-0.665,2],[-2,3.335],[-3.335,2]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ind":6,"ty":"sh","ix":7,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,-3.335],[-4.665,-2],[-6,-0.665],[-7.335,-2]],"c":true},"ix":2},"nm":"Path 7","mn":"ADBE Vector Shape - Group","hd":false},{"ind":7,"ty":"sh","ix":8,"ks":{"a":0,"k":{"i":[[-0.75,0],[0,-0.75],[0.75,0],[0,0.75]],"o":[[0.75,0],[0,0.75],[-0.75,0],[0,-0.75]],"v":[[-6,0.665],[-4.665,2],[-6,3.335],[-7.335,2]],"c":true},"ix":2},"nm":"Path 8","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":10,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Vector","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":3,"s":[0]},{"t":12,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.051,69.951,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.363,0],[0,0]],"o":[[0,0],[-2.363,0],[0,0]],"v":[[4.5,0],[-0.011,0],[-4.5,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Vector","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[18.035,13.965,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[5.686,-12.682],[0,-18.058],[-8.379,-14.991],[-10.518,-5.125],[-21.187,0],[0,0],[-8.356,4.632],[-7.57,13.076],[0,5.926],[19.097,19.964],[0,0],[13.777,0],[0,0],[10.126,-7.646]],"o":[[-5.686,12.682],[0,17.428],[8.379,14.991],[10.518,5.125],[0,0],[21.187,0],[12.419,-6.413],[7.57,-13.076],[0,-11.57],[0,0],[-19.906,-19.168],[0,0],[-15.925,0],[-10.126,7.646]],"v":[[-101.485,-20.984],[-111.35,20.572],[-98.733,67.109],[-63.133,101.229],[-20.41,111.85],[-20.308,111.85],[23.665,100.43],[57.273,68.164],[65.15,41.804],[40.217,-9.838],[9.904,-40.28],[-41.128,-65.15],[-41.229,-65.15],[-74.451,-52.874]],"c":true}]},{"t":12,"s":[{"i":[[6.107,-14.743],[0,-28.034],[-4.58,-11.057],[-14.743,-6.107],[-28.034,0],[0,0],[-11.057,4.58],[-6.107,14.743],[0,28.034],[4.58,11.057],[14.743,6.107],[28.034,0],[0,0],[11.057,-4.58]],"o":[[-4.58,11.057],[0,28.034],[6.107,14.743],[11.057,4.58],[0,0],[28.034,0],[14.743,-6.107],[4.58,-11.057],[0,-28.034],[-6.107,-14.743],[-11.057,-4.58],[0,0],[-28.034,0],[-14.743,6.107]],"v":[[-165.437,-33.008],[-170.017,20.1],[-165.437,73.208],[-132.875,105.77],[-79.767,110.35],[-19.6,110.35],[33.508,105.77],[66.07,73.208],[70.65,20.1],[66.07,-33.008],[33.508,-65.57],[-19.6,-70.15],[-79.767,-70.15],[-132.875,-65.57]],"c":true}]}],"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,-0.929],[0,0],[-4.447,0],[0,0],[0.409,-0.834],[0,0]],"o":[[0,0],[0.834,-0.409],[0,0],[0,4.447],[0,0],[0.929,0],[0,0],[0,0]],"v":[[-6.415,-5.735],[-6.21,-5.835],[-4.402,-4.708],[-4.402,-3.701],[3.651,4.352],[4.658,4.352],[5.785,6.16],[5.685,6.365]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[0,0],[0,-0.929],[0,0],[-4.447,0],[0,0],[0.409,-0.834],[0,0]],"o":[[0,0],[0.834,-0.409],[0,0],[0,4.447],[0,0],[0.929,0],[0,0],[0,0]],"v":[[1.335,-12.935],[1.54,-13.035],[3.348,-11.908],[3.348,-10.901],[11.401,-2.848],[12.408,-2.848],[13.535,-1.04],[13.435,-0.835]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"head","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16,16,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[10,10,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0.563,-1.25],[0,-1.781],[-0.829,-1.478],[-1.041,-0.505],[-2.097,0],[0,0],[-0.827,0.457],[-0.749,1.289],[0,0.584],[1.89,1.968],[0,0],[1.363,0],[0,0],[1.002,-0.754]],"o":[[-0.563,1.25],[0,1.718],[0.829,1.478],[1.041,0.505],[0,0],[2.097,0],[1.229,-0.632],[0.749,-1.289],[0,-1.141],[0,0],[-1.97,-1.89],[0,0],[-1.576,0],[-1.002,0.754]],"v":[[-8.007,-4.096],[-8.984,0.001],[-7.735,4.59],[-4.212,7.954],[0.016,9.001],[0.026,9.001],[4.378,7.875],[7.704,4.694],[8.484,2.095],[6.016,-2.997],[3.016,-5.999],[-2.034,-8.451],[-2.044,-8.451],[-5.332,-7.241]],"c":true}]},{"t":12,"s":[{"i":[[0.609,-1.47],[0,-2.796],[-0.457,-1.103],[-1.47,-0.609],[-2.796,0],[0,0],[-1.103,0.457],[-0.609,1.47],[0,2.796],[0.457,1.103],[1.47,0.609],[2.796,0],[0,0],[1.103,-0.457]],"o":[[-0.457,1.103],[0,2.796],[0.609,1.47],[1.103,0.457],[0,0],[2.796,0],[1.47,-0.609],[0.457,-1.103],[0,-2.796],[-0.609,-1.47],[-1.103,-0.457],[0,0],[-2.796,0],[-1.47,0.609]],"v":[[-14.543,-5.296],[-15,0],[-14.543,5.296],[-11.296,8.543],[-6,9],[0,9],[5.296,8.543],[8.543,5.296],[9,0],[8.543,-5.296],[5.296,-8.543],[0,-9],[-6,-9],[-11.296,-8.543]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.67,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[1000,1000],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 52","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":15,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/input_anim_stickerToSmile.json b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToSmile.json new file mode 100644 index 0000000000..1f209a5db8 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToSmile.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":60,"op":84,"w":30,"h":30,"nm":"stickertosmile","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Path 85","parent":6,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[100]},{"t":68,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[12.746,-12.746,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[0,0],[0.923,0],[0,0],[0,4.418],[0,0],[0.829,-0.406],[0,0]],"o":[[0,0],[0.406,-0.829],[0,0],[-4.418,0],[0,0],[0,-0.923],[0,0],[0,0]],"v":[[5.896,6.124],[5.996,5.92],[4.876,4.124],[3.876,4.124],[-4.124,-3.876],[-4.124,-4.876],[-5.92,-5.996],[-6.124,-5.896]],"c":false}]},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[5,0],[0,0],[0.829,-0.406],[0,0]],"o":[[0,0],[0.406,-0.829],[0,-0.391],[0,-5],[-0.391,0],[0,0],[-0.829,0.406],[0,0]],"v":[[5.633,6.5],[5.733,6.296],[6.613,4.5],[6.613,2.5],[-2.387,-6.5],[-4.387,-6.5],[-6.183,-5.62],[-6.387,-5.52]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path 85","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":122,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Oval 2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.043,-11.087,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[0,0,100]},{"t":70,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2.348,2.739],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":64,"op":120,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Oval","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-18.997,-11.087,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[0,0,100]},{"t":70,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[2.348,2.739],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Oval","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Ellipse 34","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,21.212,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-2.363,0],[0,0]],"o":[[0,0],[2.363,0],[0,0]],"v":[[-3.5,-0.965],[0,0.965],[3.5,-0.965]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 34","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[50]},{"t":70,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[50]},{"t":70,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Ellipse 33","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[14.728,15.259,0],"to":[0.045,-0.043,0],"ti":[-0.045,0.043,0]},{"t":70,"s":[15,15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[16.667,16.667,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":70,"s":[17.5,17.5,100]},{"t":80,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[-4.971,0],[-1.46,2.97],[1.89,1.97],[0,0],[2.35,-1.126],[0,-3.49]],"o":[[3.49,0],[1.19,-2.35],[0,0],[-1.97,-1.89],[-2.97,1.524],[0,4.971]],"v":[[0.272,8.741],[8.272,3.741],[6.272,-3.259],[3.272,-6.259],[-3.728,-8.323],[-8.728,-0.259]],"c":true}]},{"t":70,"s":[{"i":[[-4.971,0],[0,4.971],[0.599,1.205],[1.758,0.874],[1.437,0],[0,-4.971]],"o":[[4.971,0],[0,-1.437],[-0.874,-1.758],[-1.205,-0.599],[-4.971,0],[0,4.971]],"v":[[0,9],[9,0],[8.064,-4],[4,-8.064],[0,-9],[-9,0]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 33","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/emoji1016.txt b/submodules/TelegramUI/Resources/emoji1016.txt new file mode 100644 index 0000000000..6fef9e8cbe --- /dev/null +++ b/submodules/TelegramUI/Resources/emoji1016.txt @@ -0,0 +1,15 @@ +😀 😃 😄 😁 😆 😅 😂 🤣 🥲 ☺️ 😊 😇 🙂 🙃 😉 😌 😍 🥰 😘 😗 😙 😚 😋 😛 😝 😜 🤪 🤨 🧐 🤓 😎 🥸 🤩 🥳 😏 😒 😞 😔 😟 😕 🙁 ☹️ 😣 😖 😫 😩 🥺 😢 😭 😤 😠 😡 🤬 🤯 😳 🥵 🥶 😱 😨 😰 😥 😓 🤗 🤔 🤭 🤫 🤥 😶 😐 😑 😬 🙄 😯 😦 😧 😮 😲 🥱 😴 🤤 😪 😵 🤐 🥴 🤢 🤮 🤧 😷 🤒 🤕 🤑 🤠 😈 👿 👹 👺 🤡 💩 👻 💀 ☠️ 👽 👾 🤖 🎃 😺 😸 😹 😻 😼 😽 🙀 😿 😾 👋 🤚 🖐 ✋ 🖖 👌 🤌 🤏 ✌️ 🤞 🤟 🤘 🤙 👈 👉 👆 🖕 👇 ☝️ 👍 👎 ✊ 👊 🤛 🤜 👏 🙌 👐 🤲 🤝 🙏 ✍️ 💅 🤳 💪 🦾 🦵 🦿 🦶 👣 👂 🦻 👃 🫀 🫁 🧠 🦷 🦴 👀 👁 👅 👄 💋 🩸 👶 👧 🧒 👦 👩 🧑 👨 👩‍🦱 🧑‍🦱 👨‍🦱 👩‍🦰 🧑‍🦰 👨‍🦰 👱‍♀️ 👱 👱‍♂️ 👩‍🦳 🧑‍🦳 👨‍🦳 👩‍🦲 🧑‍🦲 👨‍🦲 🧔 👵 🧓 👴 👲 👳‍♀️ 👳 👳‍♂️ 🧕 👮‍♀️ 👮 👮‍♂️ 👷‍♀️ 👷 👷‍♂️ 💂‍♀️ 💂 💂‍♂️ 🕵️‍♀️ 🕵️ 🕵️‍♂️ 👩‍⚕️ 🧑‍⚕️ 👨‍⚕️ 👩‍🌾 🧑‍🌾 👨‍🌾 👩‍🍳 🧑‍🍳 👨‍🍳 👩‍🎓 🧑‍🎓 👨‍🎓 👩‍🎤 🧑‍🎤 👨‍🎤 👩‍🏫 🧑‍🏫 👨‍🏫 👩‍🏭 🧑‍🏭 👨‍🏭 👩‍💻 🧑‍💻 👨‍💻 👩‍💼 🧑‍💼 👨‍💼 👩‍🔧 🧑‍🔧 👨‍🔧 👩‍🔬 🧑‍🔬 👨‍🔬 👩‍🎨 🧑‍🎨 👨‍🎨 👩‍🚒 🧑‍🚒 👨‍🚒 👩‍✈️ 🧑‍✈️ 👨‍✈️ 👩‍🚀 🧑‍🚀 👨‍🚀 👩‍⚖️ 🧑‍⚖️ 👨‍⚖️ 👰‍♀️ 👰 👰‍♂️ 🤵‍♀️ 🤵 🤵‍♂️ 👸 🤴 🥷 🦸‍♀️ 🦸 🦸‍♂️ 🦹‍♀️ 🦹 🦹‍♂️ 🤶 🧑‍🎄 🎅 🧙‍♀️ 🧙 🧙‍♂️ 🧝‍♀️ 🧝 🧝‍♂️ 🧛‍♀️ 🧛 🧛‍♂️ 🧟‍♀️ 🧟 🧟‍♂️ 🧞‍♀️ 🧞 🧞‍♂️ 🧜‍♀️ 🧜 🧜‍♂️ 🧚‍♀️ 🧚 🧚‍♂️ 👼 🤰 🤱 👩‍🍼 🧑‍🍼 👨‍🍼 🙇‍♀️ 🙇 🙇‍♂️ 💁‍♀️ 💁 💁‍♂️ 🙅‍♀️ 🙅 🙅‍♂️ 🙆‍♀️ 🙆 🙆‍♂️ 🙋‍♀️ 🙋 🙋‍♂️ 🧏‍♀️ 🧏 🧏‍♂️ 🤦‍♀️ 🤦 🤦‍♂️ 🤷‍♀️ 🤷 🤷‍♂️ 🙎‍♀️ 🙎 🙎‍♂️ 🙍‍♀️ 🙍 🙍‍♂️ 💇‍♀️ 💇 💇‍♂️ 💆‍♀️ 💆 💆‍♂️ 🧖‍♀️ 🧖 🧖‍♂️ 💅 🤳 💃 🕺 👯‍♀️ 👯 👯‍♂️ 🕴 👩‍🦽 🧑‍🦽 👨‍🦽 👩‍🦼 🧑‍🦼 👨‍🦼 🚶‍♀️ 🚶 🚶‍♂️ 👩‍🦯 🧑‍🦯 👨‍🦯 🧎‍♀️ 🧎 🧎‍♂️ 🏃‍♀️ 🏃 🏃‍♂️ 🧍‍♀️ 🧍 🧍‍♂️ 👭 🧑‍🤝‍🧑 👬 👫 👩‍❤️‍👩 💑 👨‍❤️‍👨 👩‍❤️‍👨 👩‍❤️‍💋‍👩 💏 👨‍❤️‍💋‍👨 👩‍❤️‍💋‍👨 👪 👨‍👩‍👦 👨‍👩‍👧 👨‍👩‍👧‍👦 👨‍👩‍👦‍👦 👨‍👩‍👧‍👧 👨‍👨‍👦 👨‍👨‍👧 👨‍👨‍👧‍👦 👨‍👨‍👦‍👦 👨‍👨‍👧‍👧 👩‍👩‍👦 👩‍👩‍👧 👩‍👩‍👧‍👦 👩‍👩‍👦‍👦 👩‍👩‍👧‍👧 👨‍👦 👨‍👦‍👦 👨‍👧 👨‍👧‍👦 👨‍👧‍👧 👩‍👦 👩‍👦‍👦 👩‍👧 👩‍👧‍👦 👩‍👧‍👧 🗣 👤 👥 🫂 🧳 🌂 ☂️ 🧵 🪡 🪢 🧶 👓 🕶 🥽 🥼 🦺 👔 👕 👖 🧣 🧤 🧥 🧦 👗 👘 🥻 🩴 🩱 🩲 🩳 👙 👚 👛 👜 👝 🎒 👞 👟 🥾 🥿 👠 👡 🩰 👢 👑 👒 🎩 🎓 🧢 ⛑ 🪖 💄 💍 💼 + +🐶 🐱 🐭 🐹 🐰 🦊 🐻 🐼 🐻‍❄️ 🐨 🐯 🦁 🐮 🐷 🐽 🐸 🐵 🙈 🙉 🙊 🐒 🐔 🐧 🐦 🐤 🐣 🐥 🦆 🦅 🦉 🦇 🐺 🐗 🐴 🦄 🐝 🪱 🐛 🦋 🐌 🐞 🐜 🪰 🪲 🪳 🦟 🦗 🕷 🕸 🦂 🐢 🐍 🦎 🦖 🦕 🐙 🦑 🦐 🦞 🦀 🐡 🐠 🐟 🐬 🐳 🐋 🦈 🐊 🐅 🐆 🦓 🦍 🦧 🦣 🐘 🦛 🦏 🐪 🐫 🦒 🦘 🦬 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🦙 🐐 🦌 🐕 🐩 🦮 🐕‍🦺 🐈 🐈‍⬛ 🪶 🐓 🦃 🦤 🦚 🦜 🦢 🦩 🕊 🐇 🦝 🦨 🦡 🦫 🦦 🦥 🐁 🐀 🐿 🦔 🐾 🐉 🐲 🌵 🎄 🌲 🌳 🌴 🪵 🌱 🌿 ☘️ 🍀 🎍 🪴 🎋 🍃 🍂 🍁 🍄 🐚 🪨 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻 🌞 🌝 🌛 🌜 🌚 🌕 🌖 🌗 🌘 🌑 🌒 🌓 🌔 🌙 🌎 🌍 🌏 🪐 💫 ⭐️ 🌟 ✨ ⚡️ ☄️ 💥 🔥 🌪 🌈 ☀️ 🌤 ⛅️ 🌥 ☁️ 🌦 🌧 ⛈ 🌩 🌨 ❄️ ☃️ ⛄️ 🌬 💨 💧 💦 ☔️ ☂️ 🌊 🌫 + +🍏 🍎 🍐 🍊 🍋 🍌 🍉 🍇 🍓 🫐 🍈 🍒 🍑 🥭 🍍 🥥 🥝 🍅 🍆 🥑 🥦 🥬 🥒 🌶 🫑 🌽 🥕 🫒 🧄 🧅 🥔 🍠 🥐 🥯 🍞 🥖 🥨 🧀 🥚 🍳 🧈 🥞 🧇 🥓 🥩 🍗 🍖 🦴 🌭 🍔 🍟 🍕 🫓 🥪 🥙 🧆 🌮 🌯 🫔 🥗 🥘 🫕 🥫 🍝 🍜 🍲 🍛 🍣 🍱 🥟 🦪 🍤 🍙 🍚 🍘 🍥 🥠 🥮 🍢 🍡 🍧 🍨 🍦 🥧 🧁 🍰 🎂 🍮 🍭 🍬 🍫 🍿 🍩 🍪 🌰 🥜 🍯 🥛 🍼 🫖 ☕️ 🍵 🧃 🥤 🧋 🍶 🍺 🍻 🥂 🍷 🥃 🍸 🍹 🧉 🍾 🧊 🥄 🍴 🍽 🥣 🥡 🥢 🧂 + +⚽️ 🏀 🏈 ⚾️ 🥎 🎾 🏐 🏉 🥏 🎱 🪀 🏓 🏸 🏒 🏑 🥍 🏏 🪃 🥅 ⛳️ 🪁 🏹 🎣 🤿 🥊 🥋 🎽 🛹 🛼 🛷 ⛸ 🥌 🎿 ⛷ 🏂 🪂 🏋️‍♀️ 🏋️ 🏋️‍♂️ 🤼‍♀️ 🤼 🤼‍♂️ 🤸‍♀️ 🤸 🤸‍♂️ ⛹️‍♀️ ⛹️ ⛹️‍♂️ 🤺 🤾‍♀️ 🤾 🤾‍♂️ 🏌️‍♀️ 🏌️ 🏌️‍♂️ 🏇 🧘‍♀️ 🧘 🧘‍♂️ 🏄‍♀️ 🏄 🏄‍♂️ 🏊‍♀️ 🏊 🏊‍♂️ 🤽‍♀️ 🤽 🤽‍♂️ 🚣‍♀️ 🚣 🚣‍♂️ 🧗‍♀️ 🧗 🧗‍♂️ 🚵‍♀️ 🚵 🚵‍♂️ 🚴‍♀️ 🚴 🚴‍♂️ 🏆 🥇 🥈 🥉 🏅 🎖 🏵 🎗 🎫 🎟 🎪 🤹 🤹‍♂️ 🤹‍♀️ 🎭 🩰 🎨 🎬 🎤 🎧 🎼 🎹 🥁 🪘 🎷 🎺 🪗 🎸 🪕 🎻 🎲 ♟ 🎯 🎳 🎮 🎰 🧩 + +🚗 🚕 🚙 🚌 🚎 🏎 🚓 🚑 🚒 🚐 🛻 🚚 🚛 🚜 🦯 🦽 🦼 🛴 🚲 🛵 🏍 🛺 🚨 🚔 🚍 🚘 🚖 🚡 🚠 🚟 🚃 🚋 🚞 🚝 🚄 🚅 🚈 🚂 🚆 🚇 🚊 🚉 ✈️ 🛫 🛬 🛩 💺 🛰 🚀 🛸 🚁 🛶 ⛵️ 🚤 🛥 🛳 ⛴ 🚢 ⚓️ 🪝 ⛽️ 🚧 🚦 🚥 🚏 🗺 🗿 🗽 🗼 🏰 🏯 🏟 🎡 🎢 🎠 ⛲️ ⛱ 🏖 🏝 🏜 🌋 ⛰ 🏔 🗻 🏕 ⛺️ 🛖 🏠 🏡 🏘 🏚 🏗 🏭 🏢 🏬 🏣 🏤 🏥 🏦 🏨 🏪 🏫 🏩 💒 🏛 ⛪️ 🕌 🕍 🛕 🕋 ⛩ 🛤 🛣 🗾 🎑 🏞 🌅 🌄 🌠 🎇 🎆 🌇 🌆 🏙 🌃 🌌 🌉 🌁 + +⌚️ 📱 📲 💻 ⌨️ 🖥 🖨 🖱 🖲 🕹 🗜 💽 💾 💿 📀 📼 📷 📸 📹 🎥 📽 🎞 📞 ☎️ 📟 📠 📺 📻 🎙 🎚 🎛 🧭 ⏱ ⏲ ⏰ 🕰 ⌛️ ⏳ 📡 🔋 🔌 💡 🔦 🕯 🪔 🧯 🛢 💸 💵 💴 💶 💷 🪙 💰 💳 💎 ⚖️ 🪜 🧰 🪛 🔧 🔨 ⚒ 🛠 ⛏ 🪚 🔩 ⚙️ 🪤 🧱 ⛓ 🧲 🔫 💣 🧨 🪓 🔪 🗡 ⚔️ 🛡 🚬 ⚰️ 🪦 ⚱️ 🏺 🔮 📿 🧿 💈 ⚗️ 🔭 🔬 🕳 🩹 🩺 💊 💉 🩸 🧬 🦠 🧫 🧪 🌡 🧹 🪠 🧺 🧻 🚽 🚰 🚿 🛁 🛀 🧼 🪥 🪒 🧽 🪣 🧴 🛎 🔑 🗝 🚪 🪑 🛋 🛏 🛌 🧸 🪆 🖼 🪞 🪟 🛍 🛒 🎁 🎈 🎏 🎀 🪄 🪅 🎊 🎉 🎎 🏮 🎐 🧧 ✉️ 📩 📨 📧 💌 📥 📤 📦 🏷 🪧 📪 📫 📬 📭 📮 📯 📜 📃 📄 📑 🧾 📊 📈 📉 🗒 🗓 📆 📅 🗑 📇 🗃 🗳 🗄 📋 📁 📂 🗂 🗞 📰 📓 📔 📒 📕 📗 📘 📙 📚 📖 🔖 🧷 🔗 📎 🖇 📐 📏 🧮 📌 📍 ✂️ 🖊 🖋 ✒️ 🖌 🖍 📝 ✏️ 🔍 🔎 🔏 🔐 🔒 🔓 + +❤️ 🧡 💛 💚 💙 💜 🖤 🤍 🤎 💔 ❣️ 💕 💞 💓 💗 💖 💘 💝 💟 ☮️ ✝️ ☪️ 🕉 ☸️ ✡️ 🔯 🕎 ☯️ ☦️ 🛐 ⛎ ♈️ ♉️ ♊️ ♋️ ♌️ ♍️ ♎️ ♏️ ♐️ ♑️ ♒️ ♓️ 🆔 ⚛️ 🉑 ☢️ ☣️ 📴 📳 🈶 🈚️ 🈸 🈺 🈷️ ✴️ 🆚 💮 🉐 ㊙️ ㊗️ 🈴 🈵 🈹 🈲 🅰️ 🅱️ 🆎 🆑 🅾️ 🆘 ❌ ⭕️ 🛑 ⛔️ 📛 🚫 💯 💢 ♨️ 🚷 🚯 🚳 🚱 🔞 📵 🚭 ❗️ ❕ ❓ ❔ ‼️ ⁉️ 🔅 🔆 〽️ ⚠️ 🚸 🔱 ⚜️ 🔰 ♻️ ✅ 🈯️ 💹 ❇️ ✳️ ❎ 🌐 💠 Ⓜ️ 🌀 💤 🏧 🚾 ♿️ 🅿️ 🛗 🈳 🈂️ 🛂 🛃 🛄 🛅 🚹 🚺 🚼 ⚧ 🚻 🚮 🎦 📶 🈁 🔣 ℹ️ 🔤 🔡 🔠 🆖 🆗 🆙 🆒 🆕 🆓 0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟 🔢 #️⃣ *️⃣ ⏏️ ▶️ ⏸ ⏯ ⏹ ⏺ ⏭ ⏮ ⏩ ⏪ ⏫ ⏬ ◀️ 🔼 🔽 ➡️ ⬅️ ⬆️ ⬇️ ↗️ ↘️ ↙️ ↖️ ↕️ ↔️ ↪️ ↩️ ⤴️ ⤵️ 🔀 🔁 🔂 🔄 🔃 🎵 🎶 ➕ ➖ ➗ ✖️ ♾ 💲 💱 ™️ ©️ ®️ 〰️ ➰ ➿ 🔚 🔙 🔛 🔝 🔜 ✔️ ☑️ 🔘 🔴 🟠 🟡 🟢 🔵 🟣 ⚫️ ⚪️ 🟤 🔺 🔻 🔸 🔹 🔶 🔷 🔳 🔲 ▪️ ▫️ ◾️ ◽️ ◼️ ◻️ 🟥 🟧 🟨 🟩 🟦 🟪 ⬛️ ⬜️ 🟫 🔈 🔇 🔉 🔊 🔔 🔕 📣 📢 👁‍🗨 💬 💭 🗯 ♠️ ♣️ ♥️ ♦️ 🃏 🎴 🀄️ 🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛 🕜 🕝 🕞 🕟 🕠 🕡 🕢 🕣 🕤 🕥 🕦 🕧 + +🏳️ 🏴 🏁 🚩 🏳️‍🌈 🏳️‍⚧️ 🏴‍☠️ 🇦🇫 🇦🇽 🇦🇱 🇩🇿 🇦🇸 🇦🇩 🇦🇴 🇦🇮 🇦🇶 🇦🇬 🇦🇷 🇦🇲 🇦🇼 🇦🇺 🇦🇹 🇦🇿 🇧🇸 🇧🇭 🇧🇩 🇧🇧 🇧🇾 🇧🇪 🇧🇿 🇧🇯 🇧🇲 🇧🇹 🇧🇴 🇧🇦 🇧🇼 🇧🇷 🇮🇴 🇻🇬 🇧🇳 🇧🇬 🇧🇫 🇧🇮 🇰🇭 🇨🇲 🇨🇦 🇮🇨 🇨🇻 🇧🇶 🇰🇾 🇨🇫 🇹🇩 🇨🇱 🇨🇳 🇨🇽 🇨🇨 🇨🇴 🇰🇲 🇨🇬 🇨🇩 🇨🇰 🇨🇷 🇨🇮 🇭🇷 🇨🇺 🇨🇼 🇨🇾 🇨🇿 🇩🇰 🇩🇯 🇩🇲 🇩🇴 🇪🇨 🇪🇬 🇸🇻 🇬🇶 🇪🇷 🇪🇪 🇪🇹 🇪🇺 🇫🇰 🇫🇴 🇫🇯 🇫🇮 🇫🇷 🇬🇫 🇵🇫 🇹🇫 🇬🇦 🇬🇲 🇬🇪 🇩🇪 🇬🇭 🇬🇮 🇬🇷 🇬🇱 🇬🇩 🇬🇵 🇬🇺 🇬🇹 🇬🇬 🇬🇳 🇬🇼 🇬🇾 🇭🇹 🇭🇳 🇭🇰 🇭🇺 🇮🇸 🇮🇳 🇮🇩 🇮🇷 🇮🇶 🇮🇪 🇮🇲 🇮🇱 🇮🇹 🇯🇲 🇯🇵 🎌 🇯🇪 🇯🇴 🇰🇿 🇰🇪 🇰🇮 🇽🇰 🇰🇼 🇰🇬 🇱🇦 🇱🇻 🇱🇧 🇱🇸 🇱🇷 🇱🇾 🇱🇮 🇱🇹 🇱🇺 🇲🇴 🇲🇰 🇲🇬 🇲🇼 🇲🇾 🇲🇻 🇲🇱 🇲🇹 🇲🇭 🇲🇶 🇲🇷 🇲🇺 🇾🇹 🇲🇽 🇫🇲 🇲🇩 🇲🇨 🇲🇳 🇲🇪 🇲🇸 🇲🇦 🇲🇿 🇲🇲 🇳🇦 🇳🇷 🇳🇵 🇳🇱 🇳🇨 🇳🇿 🇳🇮 🇳🇪 🇳🇬 🇳🇺 🇳🇫 🇰🇵 🇲🇵 🇳🇴 🇴🇲 🇵🇰 🇵🇼 🇵🇸 🇵🇦 🇵🇬 🇵🇾 🇵🇪 🇵🇭 🇵🇳 🇵🇱 🇵🇹 🇵🇷 🇶🇦 🇷🇪 🇷🇴 🇷🇺 🇷🇼 🇼🇸 🇸🇲 🇸🇦 🇸🇳 🇷🇸 🇸🇨 🇸🇱 🇸🇬 🇸🇽 🇸🇰 🇸🇮 🇬🇸 🇸🇧 🇸🇴 🇿🇦 🇰🇷 🇸🇸 🇪🇸 🇱🇰 🇧🇱 🇸🇭 🇰🇳 🇱🇨 🇵🇲 🇻🇨 🇸🇩 🇸🇷 🇸🇿 🇸🇪 🇨🇭 🇸🇾 🇹🇼 🇹🇯 🇹🇿 🇹🇭 🇹🇱 🇹🇬 🇹🇰 🇹🇴 🇹🇹 🇹🇳 🇹🇷 🇹🇲 🇹🇨 🇹🇻 🇻🇮 🇺🇬 🇺🇦 🇦🇪 🇬🇧 🏴󠁧󠁢󠁥󠁮󠁧󠁿 🏴󠁧󠁢󠁳󠁣󠁴󠁿 🏴󠁧󠁢󠁷󠁬󠁳󠁿 🇺🇳 🇺🇸 🇺🇾 🇺🇿 🇻🇺 🇻🇦 🇻🇪 🇻🇳 🇼🇫 🇪🇭 🇾🇪 🇿🇲 🇿🇼 diff --git a/submodules/TelegramUI/Sources/AccountContext.swift b/submodules/TelegramUI/Sources/AccountContext.swift index 944d5bcb33..5303f74f6e 100644 --- a/submodules/TelegramUI/Sources/AccountContext.swift +++ b/submodules/TelegramUI/Sources/AccountContext.swift @@ -186,11 +186,8 @@ public final class AccountContextImpl: AccountContext { self.prefetchManager = PrefetchManagerImpl(sharedContext: sharedContext, account: account, engine: self.engine, fetchManager: self.fetchManager) self.wallpaperUploadManager = WallpaperUploadManagerImpl(sharedContext: sharedContext, account: account, presentationData: sharedContext.presentationData) self.themeUpdateManager = ThemeUpdateManagerImpl(sharedContext: sharedContext, account: account) - if let premiumProductId = sharedContext.premiumProductId { - self.inAppPurchaseManager = InAppPurchaseManager(engine: self.engine, premiumProductId: premiumProductId) - } else { - self.inAppPurchaseManager = nil - } + + self.inAppPurchaseManager = InAppPurchaseManager(engine: self.engine) } else { self.prefetchManager = nil self.wallpaperUploadManager = nil diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index e8bef330e6..ce15158246 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -773,7 +773,7 @@ private func extractAccountManagerState(records: AccountRecordsView Void)? - let sharedContext = SharedAccountContextImpl(mainWindow: self.mainWindow, sharedContainerPath: legacyBasePath, basePath: rootPath, encryptionParameters: encryptionParameters, accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings, networkArguments: networkArguments, premiumProductId: buildConfig.premiumIAPProductId, rootPath: rootPath, legacyBasePath: legacyBasePath, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in + let sharedContext = SharedAccountContextImpl(mainWindow: self.mainWindow, sharedContainerPath: legacyBasePath, basePath: rootPath, encryptionParameters: encryptionParameters, accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings, networkArguments: networkArguments, hasInAppPurchases: buildConfig.isAppStoreBuild && buildConfig.apiId == 1, rootPath: rootPath, legacyBasePath: legacyBasePath, apsNotificationToken: self.notificationTokenPromise.get() |> map(Optional.init), voipNotificationToken: self.voipTokenPromise.get() |> map(Optional.init), setNotificationCall: { call in setPresentationCall?(call) }, navigateToChat: { accountId, peerId, messageId in self.openChatWhenReady(accountId: accountId, peerId: peerId, messageId: messageId) @@ -2000,7 +2000,7 @@ private func extractAccountManagerState(records: AccountRecordsView map { messageIds -> MessageId? in if messageIds.isEmpty { return nil diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift index 7e3eddae93..0989039718 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceController.swift @@ -305,7 +305,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail } var dismissImpl: (() -> Void)? let alertTheme = AlertControllerTheme(presentationData: strongSelf.presentationData) - let attributedText = stringWithAppliedEntities(termsOfService.text, entities: termsOfService.entities, baseColor: alertTheme.primaryColor, linkColor: alertTheme.accentColor, baseFont: Font.regular(13.0), linkFont: Font.regular(13.0), boldFont: Font.semibold(13.0), italicFont: Font.italic(13.0), boldItalicFont: Font.semiboldItalic(13.0), fixedFont: Font.regular(13.0), blockQuoteFont: Font.regular(13.0)) + let attributedText = stringWithAppliedEntities(termsOfService.text, entities: termsOfService.entities, baseColor: alertTheme.primaryColor, linkColor: alertTheme.accentColor, baseFont: Font.regular(13.0), linkFont: Font.regular(13.0), boldFont: Font.semibold(13.0), italicFont: Font.italic(13.0), boldItalicFont: Font.semiboldItalic(13.0), fixedFont: Font.regular(13.0), blockQuoteFont: Font.regular(13.0), message: nil) let contentNode = TextAlertContentNode(theme: alertTheme, title: NSAttributedString(string: strongSelf.presentationData.strings.Login_TermsOfServiceHeader, font: Font.medium(17.0), textColor: alertTheme.primaryColor, paragraphAlignment: .center), text: attributedText, actions: [ TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Login_TermsOfServiceAgree, action: { dismissImpl?() diff --git a/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift b/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift index 9006758168..c657ec572d 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequencePhoneEntryController.swift @@ -129,7 +129,7 @@ final class AuthorizationSequencePhoneEntryController: ViewController { strongSelf.controllerNode.activateInput() } } - controller.dismissed = { + controller.dismissed = { self?.controllerNode.activateInput() } strongSelf.push(controller) diff --git a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift index fc5b3f0180..67c3eb0d1a 100644 --- a/submodules/TelegramUI/Sources/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/Sources/ChatBotInfoItem.swift @@ -207,7 +207,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { updatedTextAndEntities = (item.text, generateTextEntities(item.text, enabledTypes: .all)) } - let attributedText = stringWithAppliedEntities(updatedTextAndEntities.0, entities: updatedTextAndEntities.1, baseColor: item.presentationData.theme.theme.chat.message.infoPrimaryTextColor, linkColor: item.presentationData.theme.theme.chat.message.infoLinkTextColor, baseFont: messageFont, linkFont: messageFont, boldFont: messageBoldFont, italicFont: messageItalicFont, boldItalicFont: messageBoldItalicFont, fixedFont: messageFixedFont, blockQuoteFont: messageFont) + let attributedText = stringWithAppliedEntities(updatedTextAndEntities.0, entities: updatedTextAndEntities.1, baseColor: item.presentationData.theme.theme.chat.message.infoPrimaryTextColor, linkColor: item.presentationData.theme.theme.chat.message.infoLinkTextColor, baseFont: messageFont, linkFont: messageFont, boldFont: messageBoldFont, italicFont: messageItalicFont, boldItalicFont: messageBoldItalicFont, fixedFont: messageFixedFont, blockQuoteFont: messageFont, message: nil) let horizontalEdgeInset: CGFloat = 10.0 + params.leftInset let horizontalContentInset: CGFloat = 12.0 diff --git a/submodules/TelegramUI/Sources/ChatBotStartInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatBotStartInputPanelNode.swift index df7ddf406e..028769b5ec 100644 --- a/submodules/TelegramUI/Sources/ChatBotStartInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatBotStartInputPanelNode.swift @@ -89,7 +89,7 @@ final class ChatBotStartInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.sendBotStart(presentationInterfaceState.botStartPayload) } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState } diff --git a/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift index 51ca4407d7..5e1898e644 100644 --- a/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift @@ -115,7 +115,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) { transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: UIScreenPixel))) let updatedTheme = self.theme !== interfaceState.theme diff --git a/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift index b79d0bab44..d75ce83bff 100644 --- a/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift @@ -265,7 +265,7 @@ final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { return self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, force: false) } diff --git a/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift b/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift index 3a81998162..d53796a5e9 100644 --- a/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatContextResultPeekContentNode.swift @@ -147,6 +147,10 @@ private final class ChatContextResultPeekNode: ASDisplayNode, PeekControllerCont } } + func ready() -> Signal { + return .single(true) + } + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { let imageLayout = self.imageNode.asyncLayout() let currentImageResource = self.currentImageResource diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 5fd0ef4b1a..132c6f37d9 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -78,6 +78,8 @@ import ChatTextLinkEditUI import WebUI import PremiumUI import ImageTransparency +import StickerPackPreviewUI +import TextNodeWithEntities #if DEBUG import os.signpost @@ -292,6 +294,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private let loadingMessage = Promise(nil) private let performingInlineSearch = ValuePromise(false, ignoreRepeated: true) + private var stateServiceTasks: [AnyHashable: Disposable] = [:] + private var preloadHistoryPeerId: PeerId? private let preloadHistoryPeerIdDisposable = MetaDisposable() @@ -770,6 +774,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .setChatTheme: strongSelf.presentThemeSelection() return true + case let .giftPremium(_, _, duration): + let fromPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? strongSelf.context.account.peerId : message.id.peerId + let toPeerId: PeerId = message.author?.id == strongSelf.context.account.peerId ? message.id.peerId : strongSelf.context.account.peerId + let controller = PremiumIntroScreen(context: strongSelf.context, source: .gift(from: fromPeerId, to: toPeerId, duration: duration)) + strongSelf.push(controller) + return true default: break } @@ -816,7 +826,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, enqueueMessage: { message in self?.sendMessages([message]) }, sendSticker: canSendMessagesToChat(strongSelf.presentationInterfaceState) ? { fileReference, sourceNode, sourceRect in - return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) ?? false + return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) ?? false } : nil, setupTemporaryHiddenMedia: { signal, centralIndex, galleryMedia in if let strongSelf = self { strongSelf.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).start(next: { entry in @@ -917,8 +927,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G transitionCompletion() }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -949,6 +959,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if strongSelf.presentationInterfaceState.interfaceState.selectionState != nil { return } + let presentationData = strongSelf.presentationData strongSelf.dismissAllTooltips() @@ -997,7 +1008,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } var tip: ContextController.Tip? - + if tip == nil { var isAction = false for media in message.media { @@ -1030,7 +1041,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } actions.context = strongSelf.context - + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) if canAddMessageReactions(message: topMessage), let availableReactions = availableReactions, let allowedReactions = allowedReactions { @@ -1078,7 +1089,119 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: message, selectAll: selectAll)), items: .single(actions), recognizer: recognizer, gesture: gesture) + let presentationContext = strongSelf.controllerInteraction?.presentationContext + + var disableTransitionAnimations = false + var actionsSignal: Signal = .single(actions) + if let entitiesAttribute = message.textEntitiesAttribute { + var emojiFileIds: [Int64] = [] + for entity in entitiesAttribute.entities { + if case let .CustomEmoji(_, fileId) = entity.type { + emojiFileIds.append(fileId) + } + } + if !emojiFileIds.isEmpty { + tip = .animatedEmoji(text: nil, arguments: nil, file: nil, action: nil) + actions.tip = tip + disableTransitionAnimations = true + + actionsSignal = .single(actions) + |> then( + context.engine.stickers.resolveInlineStickers(fileIds: emojiFileIds) + |> mapToSignal { files -> Signal in + var packReferences: [StickerPackReference] = [] + var existingIds = Set() + for (_, file) in files { + loop: for attribute in file.attributes { + if case let .CustomEmoji(_, _, packReference) = attribute, let packReference = packReference { + if case let .id(id, _) = packReference, !existingIds.contains(id) { + packReferences.append(packReference) + existingIds.insert(id) + } + break loop + } + } + } + + let action = { + guard let packReference = packReferences.first, let strongSelf = self else { + return + } + strongSelf.chatDisplayNode.dismissTextInput() + + let presentationData = strongSelf.presentationData + let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController, actionPerformed: { [weak self] actions in + guard let strongSelf = self else { + return + } + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + } + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + + switch action { + case .add: + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + case let .remove(positionInList): + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in + if case .undo = action { + let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } + } + }) + strongSelf.present(controller, in: .window(.root)) + } + + if packReferences.count > 1 { + actions.tip = .animatedEmoji(text: presentationData.strings.ChatContextMenu_EmojiSet(Int32(packReferences.count)), arguments: nil, file: nil, action: action) + return .single(actions) + } else if let reference = packReferences.first { + return context.engine.stickers.loadedStickerPack(reference: reference, forceActualized: false) + |> filter { result in + if case .result = result { + return true + } else { + return false + } + } + |> mapToSignal { result in + if case let .result(info, items, _) = result, let presentationContext = presentationContext { + actions.tip = .animatedEmoji( + text: presentationData.strings.ChatContextMenu_EmojiSetSingle(info.title).string, + arguments: TextNodeWithEntities.Arguments( + context: context, + cache: presentationContext.animationCache, + renderer: presentationContext.animationRenderer, + placeholderColor: .clear, + attemptSynchronous: true + ), + file: items.first?.file, + action: action) + return .single(actions) + } else { + return .complete() + } + } + } else { + actions.tip = nil + return .single(actions) + } + } + ) + } + } + + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, engine: strongSelf.context.engine, message: message, selectAll: selectAll)), items: actionsSignal, recognizer: recognizer, gesture: gesture) + controller.immediateItemsTransitionAnimation = disableTransitionAnimations controller.getOverlayViews = { [weak self] in guard let strongSelf = self else { return [] @@ -1483,6 +1606,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -1493,14 +1618,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: text, attributes: attributes, mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)]) - }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceNode, sourceRect in + strongSelf.sendMessages([.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)]) + }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in guard let strongSelf = self else { return false } if let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode, sourceRect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceView, sourceRect) return false } @@ -1517,12 +1642,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } var shouldAnimateMessageTransition = strongSelf.chatDisplayNode.shouldAnimateMessageTransition - if sourceNode is ChatEmptyNodeStickerContentNode { + if let _ = sourceView.asyncdisplaykit_node as? ChatEmptyNodeStickerContentNode { shouldAnimateMessageTransition = true } strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { current in var current = current current = current.updatedInterfaceState { interfaceState in @@ -1545,7 +1672,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, shouldAnimateMessageTransition ? correlationId : nil) if shouldAnimateMessageTransition { - if let sourceNode = sourceNode as? ChatMediaInputStickerGridItemNode { + if let sourceNode = sourceView.asyncdisplaykit_node as? ChatMediaInputStickerGridItemNode { strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .inputPanel(itemNode: sourceNode), replyPanel: replyPanel), initiated: { guard let strongSelf = self else { return @@ -1562,16 +1689,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return current }) }) - } else if let sourceNode = sourceNode as? HorizontalStickerGridItemNode { + } else if let sourceNode = sourceView.asyncdisplaykit_node as? HorizontalStickerGridItemNode { strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .mediaPanel(itemNode: sourceNode), replyPanel: replyPanel), initiated: {}) - } else if let sourceNode = sourceNode as? StickerPaneSearchStickerItemNode { + } else if let sourceNode = sourceView.asyncdisplaykit_node as? StickerPaneSearchStickerItemNode { strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .inputPanelSearch(itemNode: sourceNode), replyPanel: replyPanel), initiated: {}) - } else if let sourceNode = sourceNode as? ChatEmptyNodeStickerContentNode { + } else if let sourceNode = sourceView.asyncdisplaykit_node as? ChatEmptyNodeStickerContentNode { strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .emptyPanel(itemNode: sourceNode), replyPanel: nil), initiated: {}) + } else if let sourceLayer = sourceLayer { + strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .universal(sourceContainerView: sourceView, sourceRect: sourceRect, sourceLayer: sourceLayer), replyPanel: replyPanel), initiated: { + guard let strongSelf = self else { + return + } + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { current in + var current = current + current = current.updatedInputMode { current in + if case let .media(mode, maybeExpanded, focused) = current, maybeExpanded != nil { + return .media(mode: mode, expanded: nil, focused: focused) + } + return current + } + + return current + }) + }) } } - let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)] + let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)] if silentPosting { let transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting) strongSelf.sendMessages(transformedMessages) @@ -1587,15 +1731,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.sendMessages(transformedMessages) } return true - }, sendGif: { [weak self] fileReference, sourceNode, sourceRect, silentPosting, schedule in + }, sendGif: { [weak self] fileReference, sourceView, sourceRect, silentPosting, schedule in if let strongSelf = self { if let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode, sourceRect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceView, sourceRect) return false } strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) }.updatedInputMode { current in if case let .media(mode, maybeExpanded, focused) = current, maybeExpanded != nil { @@ -1607,7 +1753,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, nil) - var messages = [EnqueueMessage.message(text: "", attributes: [], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] + var messages = [EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] if silentPosting { messages = strongSelf.transformEnqueueMessages(messages, silentPosting: true) strongSelf.sendMessages(messages) @@ -1624,7 +1770,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } return true - }, sendBotContextResultAsGif: { [weak self] collection, result, sourceNode, sourceRect, silentPosting in + }, sendBotContextResultAsGif: { [weak self] collection, result, sourceView, sourceRect, silentPosting in guard let strongSelf = self else { return false } @@ -1632,7 +1778,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return false } if let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode, sourceRect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceView, sourceRect) return false } @@ -1941,7 +2087,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> deliverOnMainQueue).start(next: { coordinate in if let strongSelf = self { if let coordinate = coordinate { - strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) } else { strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})]), in: .window(.root)) } @@ -1965,7 +2111,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId) |> deliverOnMainQueue).start(next: { peer in if let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty { - strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) } }) } @@ -1997,6 +2143,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreview(nil) } }) @@ -2007,7 +2155,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: command, attributes: attributes, mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil, correlationId: nil)]) } }, openInstantPage: { [weak self] message, associatedData in if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.effectiveNavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) { @@ -2310,7 +2458,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_Send, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() if let strongSelf = self { - strongSelf.sendMessages([.message(text: command, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) } })) } @@ -2947,7 +3095,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { if let _ = strongSelf.presentationInterfaceState.slowmodeState { if let rect = strongSelf.chatDisplayNode.frameForInputActionButton() { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode, rect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode.view, rect) } return } else { @@ -2971,7 +3119,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } } - strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in + + let inlineStickers: [MediaId: TelegramMediaFile] = [:] + strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: false, scheduleTime: time) |> deliverOnMainQueue).start(next: { result in }, error: { error in })) } @@ -3112,15 +3262,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self?.displayPsa(type: type, sourceNode: sourceNode, isAutomatic: false) }, displayDiceTooltip: { [weak self] dice in self?.displayDiceTooltip(dice: dice) - }, animateDiceSuccess: { [weak self] onlyHaptic in + }, animateDiceSuccess: { [weak self] haptic, confetti in guard let strongSelf = self else { return } if strongSelf.selectPollOptionFeedback == nil { strongSelf.selectPollOptionFeedback = HapticFeedback() } - strongSelf.selectPollOptionFeedback?.success() - if !onlyHaptic { + if haptic { + strongSelf.selectPollOptionFeedback?.success() + } + if confetti { strongSelf.chatDisplayNode.animateQuizCorrectOptionSelected() } }, displayPremiumStickerTooltip: { [weak self] file, message in @@ -3288,8 +3440,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] { legacyMediaEditor(context: strongSelf.context, peer: peer, media: mediaReference, initialCaption: NSAttributedString(string: message.text), snapshots: [], transitionCompletion: nil, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -3376,7 +3528,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(false))).start(next: { [weak self] responded in if let strongSelf = self { if !responded { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: file, title: nil, text: strongSelf.presentationData.strings.Conversation_InteractiveEmojiSyncTip(EnginePeer(peer).compactDisplayTitle).string, undoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current) + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: file, title: nil, text: strongSelf.presentationData.strings.Conversation_InteractiveEmojiSyncTip(EnginePeer(peer).compactDisplayTitle).string, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), in: .current) let _ = ApplicationSpecificNotice.incrementInteractiveEmojiSyncTip(accountManager: strongSelf.context.sharedContext.accountManager, timestamp: currentTimestamp).start() } @@ -3494,7 +3646,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, didDismiss: { [weak self] in if let strongSelf = self { let isFocused = strongSelf.chatDisplayNode.textInputPanelNode?.isFocused ?? false - strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.historyNodeContainer) + strongSelf.chatDisplayNode.insertSubnode(strongSelf.chatDisplayNode.inputPanelContainerNode, aboveSubnode: strongSelf.chatDisplayNode.inputContextPanelContainer) if isFocused { strongSelf.chatDisplayNode.textInputPanelNode?.ensureFocused() } @@ -3586,6 +3738,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, cancelInteractiveKeyboardGestures: { [weak self] in (self?.view.window as? WindowHost)?.cancelInteractiveKeyboardGestures() self?.chatDisplayNode.cancelInteractiveKeyboardGestures() + }, dismissTextInput: { [weak self] in + self?.chatDisplayNode.dismissTextInput() }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: self.stickerSettings, presentationContext: ChatPresentationContext(context: context, backgroundNode: self.chatBackgroundNode)) self.controllerInteraction = controllerInteraction @@ -5296,7 +5450,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } override public func loadDisplayNode() { - self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, backgroundNode: self.chatBackgroundNode, controller: self) + self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, statusBar: self.statusBar, backgroundNode: self.chatBackgroundNode, controller: self) if let currentItem = self.tempVoicePlaylistCurrentItem { self.chatDisplayNode.historyNode.voicePlaylistItemChanged(nil, currentItem) @@ -5592,6 +5746,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var peerIsBlocked: Bool = false var callsAvailable: Bool = false var callsPrivate: Bool = false + var voiceMessagesAvailable: Bool = true var slowmodeState: ChatSlowmodeState? var activeGroupCallInfo: ChatActiveGroupCallInfo? var inviteRequestsPending: Int32? @@ -5613,6 +5768,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G callsAvailable = cachedData.voiceCallsAvailable callsPrivate = cachedData.callsPrivate pinnedMessageId = cachedData.pinnedMessageId + voiceMessagesAvailable = cachedData.voiceMessagesAvailable } else if let cachedData = cachedData as? CachedGroupData { pinnedMessageId = cachedData.pinnedMessageId if let activeCall = cachedData.activeCall { @@ -5654,6 +5810,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let callsDataUpdated = strongSelf.presentationInterfaceState.callsAvailable != callsAvailable || strongSelf.presentationInterfaceState.callsPrivate != callsPrivate + let voiceMessagesAvailableUpdated = strongSelf.presentationInterfaceState.voiceMessagesAvailable != voiceMessagesAvailable + var canManageInvitations = false if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isCreator) || (channel.adminRights?.rights.contains(.canInviteUsers) == true) { canManageInvitations = true @@ -5736,7 +5894,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - if strongSelf.presentationInterfaceState.pinnedMessageId != pinnedMessageId || strongSelf.presentationInterfaceState.pinnedMessage != pinnedMessage || strongSelf.presentationInterfaceState.peerIsBlocked != peerIsBlocked || pinnedMessageUpdated || callsDataUpdated || strongSelf.presentationInterfaceState.slowmodeState != slowmodeState || strongSelf.presentationInterfaceState.activeGroupCallInfo != activeGroupCallInfo { + if strongSelf.presentationInterfaceState.pinnedMessageId != pinnedMessageId || strongSelf.presentationInterfaceState.pinnedMessage != pinnedMessage || strongSelf.presentationInterfaceState.peerIsBlocked != peerIsBlocked || pinnedMessageUpdated || callsDataUpdated || voiceMessagesAvailableUpdated || strongSelf.presentationInterfaceState.slowmodeState != slowmodeState || strongSelf.presentationInterfaceState.activeGroupCallInfo != activeGroupCallInfo { strongSelf.updateChatPresentationInterfaceState(animated: strongSelf.willAppear, interactive: strongSelf.willAppear, { state in return state .updatedPinnedMessageId(pinnedMessageId) @@ -5745,6 +5903,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G .updatedPeerIsBlocked(peerIsBlocked) .updatedCallsAvailable(callsAvailable) .updatedCallsPrivate(callsPrivate) + .updatedVoiceMessagesAvailable(voiceMessagesAvailable) .updatedTitlePanelContext({ context in if pinnedMessageId != nil { if !context.contains(where: { @@ -6017,7 +6176,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var correlationIds: [Int64] = [] for message in messages { switch message { - case let .message(_, _, _, _, _, correlationId): + case let .message(_, _, _, _, _, _, correlationId): if let correlationId = correlationId { correlationIds.append(correlationId) } @@ -6128,7 +6287,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if strongSelf.presentationInterfaceState.interfaceState.editMessage == nil, let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { if let rect = strongSelf.chatDisplayNode.frameForAttachmentButton() { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode, rect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode.view, rect) } return } @@ -6977,6 +7136,43 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G entitiesAttribute = TextEntitiesMessageAttribute(entities: entities) } + var inlineStickers: [MediaId: TelegramMediaFile] = [:] + var firstLockedPremiumEmoji: TelegramMediaFile? + text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + if let file = value.file { + inlineStickers[file.fileId] = file + if file.isPremiumEmoji && !strongSelf.presentationInterfaceState.isPremium { + if firstLockedPremiumEmoji == nil { + firstLockedPremiumEmoji = file + } + } + } + } + }) + + if let firstLockedPremiumEmoji = firstLockedPremiumEmoji { + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + strongSelf.controllerInteraction?.displayUndo(.sticker(context: strongSelf.context, file: firstLockedPremiumEmoji, title: nil, text: presentationData.strings.EmojiInput_PremiumEmojiToast_Text, undoText: presentationData.strings.EmojiInput_PremiumEmojiToast_Action, customAction: { + guard let strongSelf = self else { + return + } + strongSelf.chatDisplayNode.dismissTextInput() + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + strongSelf.present(controller, in: .window(.root), with: nil) + })) + + return + } + var updatingMedia = false let media: RequestEditMessageMedia if let editMediaReference = strongSelf.presentationInterfaceState.editMessageState?.mediaReference { @@ -6993,7 +7189,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let currentMessage = currentMessage { let currentEntities = currentMessage.textEntitiesAttribute?.entities ?? [] if currentMessage.text != text.string || currentEntities != entities || updatingMedia { - strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, disableUrlPreview: disableUrlPreview) + strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview) } } @@ -7197,7 +7393,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return false } if let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(node, rect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(node.view, rect) return false } @@ -7219,6 +7415,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreview(nil) } }) @@ -7229,7 +7427,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - strongSelf.sendMessages([.message(text: messageText, attributes: attributes, mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: messageText, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]) strongSelf.interfaceInteraction?.updateShowCommands { _ in return false } @@ -7255,7 +7453,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.interfaceInteraction?.updateShowWebView { _ in return false } - + let requestId = strongSelf.beginMediaRecordingRequestId let begin: () -> Void = { guard let strongSelf = self, strongSelf.beginMediaRecordingRequestId == requestId else { @@ -7284,6 +7482,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) } + DeviceAccess.authorizeAccess(to: .microphone(isVideo ? .video : .audio), presentationData: strongSelf.presentationData, present: { c, a in self?.present(c, in: .window(.root), with: a) }, openSettings: { @@ -7337,7 +7536,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G switch subject { case .stickers: subjectFlags = .banSendStickers - case .mediaRecording: + case .mediaRecording, .premiumVoiceMessages: subjectFlags = .banSendMedia } @@ -7373,6 +7572,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { banDescription = strongSelf.presentationInterfaceState.strings.Conversation_DefaultRestrictedMedia } + case .premiumVoiceMessages: + banDescription = "" } if strongSelf.recordingModeFeedback == nil { strongSelf.recordingModeFeedback = HapticFeedback() @@ -7392,7 +7593,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G rectValue.origin.y = actionRect.minY rect = rectValue } - case .mediaRecording: + case .mediaRecording, .premiumVoiceMessages: rect = strongSelf.chatDisplayNode.frameForInputActionButton() } @@ -7420,7 +7621,37 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - if case .mediaRecording = subject, strongSelf.presentationInterfaceState.hasActiveGroupCall { + if case .premiumVoiceMessages = subject { + let text: String + if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer.flatMap({ EnginePeer($0) }) { + text = strongSelf.presentationInterfaceState.strings.Conversation_VoiceMessagesRestricted(peer.compactDisplayTitle).string + } else { + text = "" + } + switch displayType { + case .tooltip: + let rect = strongSelf.chatDisplayNode.frameForInputActionButton() + if let rect = rect { + strongSelf.mediaRestrictedTooltipController?.dismiss() + let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize) + strongSelf.mediaRestrictedTooltipController = tooltipController + strongSelf.mediaRestrictedTooltipControllerMode = false + tooltipController.dismissed = { [weak tooltipController] _ in + if let strongSelf = self, let tooltipController = tooltipController, strongSelf.mediaRestrictedTooltipController === tooltipController { + strongSelf.mediaRestrictedTooltipController = nil + } + } + strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: { + if let strongSelf = self { + return (strongSelf.chatDisplayNode, rect) + } + return nil + })) + } + case .alert: + strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) + } + } else if case .mediaRecording = subject, strongSelf.presentationInterfaceState.hasActiveGroupCall { let rect = strongSelf.chatDisplayNode.frameForInputActionButton() if let rect = rect { strongSelf.mediaRestrictedTooltipController?.dismiss() @@ -7581,9 +7812,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } } - }, sendSticker: { [weak self] file, clearInput, sourceNode, sourceRect in + }, sendSticker: { [weak self] file, clearInput, sourceView, sourceRect, sourceLayer in if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) { - return strongSelf.controllerInteraction?.sendSticker(file, false, false, nil, clearInput, sourceNode, sourceRect) ?? false + return strongSelf.controllerInteraction?.sendSticker(file, false, false, nil, clearInput, sourceView, sourceRect, sourceLayer) ?? false } else { return false } @@ -7975,7 +8206,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self { switch result { case .generic: - strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: nil, text: added ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: true, action: { _ in return false }), with: nil) + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: nil, text: added ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: true, action: { _ in return false }), with: nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) let text: String @@ -7984,7 +8215,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: true, action: { [weak self] action in + strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: true, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -8240,11 +8471,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) })] strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.ReportGroupLocation_Title, text: strongSelf.presentationData.strings.ReportGroupLocation_Text, actions: actions), in: .window(.root)) - }, displaySlowmodeTooltip: { [weak self] node, nodeRect in + }, displaySlowmodeTooltip: { [weak self] sourceView, nodeRect in guard let strongSelf = self, let slowmodeState = strongSelf.presentationInterfaceState.slowmodeState else { return } - let rect = node.view.convert(nodeRect, to: strongSelf.view) + let rect = sourceView.convert(nodeRect, to: strongSelf.view) if let slowmodeTooltipController = strongSelf.slowmodeTooltipController { if let arguments = slowmodeTooltipController.presentationArguments as? TooltipControllerPresentationArguments, case let .node(f) = arguments.sourceAndRect, let (previousNode, previousRect) = f() { if previousNode === strongSelf.chatDisplayNode && previousRect == rect { @@ -8290,6 +8521,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.controllerInteraction?.scheduleCurrentMessage() } }) + controller.emojiViewProvider = strongSelf.chatDisplayNode.textInputPanelNode?.emojiViewProvider strongSelf.sendMessageActionsController = controller if layout.isNonExclusive { strongSelf.present(controller, in: .window(.root)) @@ -8559,6 +8791,37 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return $0.updatedShowWebView(f($0.showWebView)) }) } + }, insertText: { [weak self] text in + guard let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction else { + return + } + if !strongSelf.chatDisplayNode.isTextInputPanelActive { + return + } + + interfaceInteraction.updateTextInputStateAndMode { textInputState, inputMode in + let inputText = NSMutableAttributedString(attributedString: textInputState.inputText) + + let range = textInputState.selectionRange + inputText.replaceCharacters(in: NSMakeRange(range.lowerBound, range.count), with: text) + + let selectionPosition = range.lowerBound + (text.string as NSString).length + + return (ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition), inputMode) + } + + strongSelf.chatDisplayNode.updateTypingActivity(true) + }, backwardsDeleteText: { [weak self] in + guard let strongSelf = self else { + return + } + if !strongSelf.chatDisplayNode.isTextInputPanelActive { + return + } + guard let textInputPanelNode = strongSelf.chatDisplayNode.textInputPanelNode else { + return + } + textInputPanelNode.backwardsDeleteText() }, chatController: { [weak self] in return self }, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get())) @@ -8746,6 +9009,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .tooMuchScheduled: text = strongSelf.presentationData.strings.Conversation_SendMessageErrorTooMuchScheduled moreInfo = false + case .voiceMessagesForbidden: + strongSelf.interfaceInteraction?.displayRestrictedInfo(.premiumVoiceMessages, .alert) + return } let actions: [TextAlertAction] if moreInfo { @@ -9175,7 +9441,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { canSendMedia = true } - if canSendMedia { + if canSendMedia && self.presentationInterfaceState.voiceMessagesAvailable { let _ = (ApplicationSpecificNotice.getChatMediaMediaRecordingTips(accountManager: self.context.sharedContext.accountManager) |> deliverOnMainQueue).start(next: { [weak self] counter in guard let strongSelf = self else { @@ -9880,12 +10146,42 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.updateSlowmodeStatus() + switch updatedChatPresentationInterfaceState.inputMode { + case .media: + break + default: + self.chatDisplayNode.collapseInput() + } + if self.isNodeLoaded { self.chatDisplayNode.updateChatPresentationInterfaceState(updatedChatPresentationInterfaceState, transition: transition, interactive: interactive, completion: completion) } else { completion(.immediate) } + let updatedServiceTasks = serviceTasksForChatPresentationIntefaceState(context: self.context, chatPresentationInterfaceState: updatedChatPresentationInterfaceState, updateState: { [weak self] f in + guard let strongSelf = self else { + return + } + strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: false, f) + + //strongSelf.chatDisplayNode.updateChatPresentationInterfaceState(f(strongSelf.chatDisplayNode.chatPresentationInterfaceState), transition: transition, interactive: false, completion: { _ in }) + }) + for (id, begin) in updatedServiceTasks { + if self.stateServiceTasks[id] == nil { + self.stateServiceTasks[id] = begin() + } + } + var removedServiceTaskIds: [AnyHashable] = [] + for (id, _) in self.stateServiceTasks { + if updatedServiceTasks[id] == nil { + removedServiceTaskIds.append(id) + } + } + for id in removedServiceTaskIds { + self.stateServiceTasks.removeValue(forKey: id)?.dispose() + } + if let button = leftNavigationButtonForChatInterfaceState(updatedChatPresentationInterfaceState, subject: self.subject, strings: updatedChatPresentationInterfaceState.strings, currentButton: self.leftNavigationButton, target: self, selector: #selector(self.leftNavigationButtonAction)) { if self.leftNavigationButton != button { var animated = transition.isAnimated @@ -9930,20 +10226,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - switch updatedChatPresentationInterfaceState.mode { - case .standard: - if self.hasEmbeddedTitleContent { - self.statusBar.statusBarStyle = .White - } else { - self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style - } - self.deferScreenEdgeGestures = [] - case .overlay: - self.deferScreenEdgeGestures = [.top] - case .inline: - self.statusBar.statusBarStyle = .Ignore - } - if saveInterfaceState { self.saveInterfaceState(includeScrollState: false) } @@ -10586,7 +10868,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } private func editMessageMediaWithMessages(_ messages: [EnqueueMessage]) { - if let message = messages.first, case let .message(text, attributes, maybeMediaReference, _, _, _) = message, let mediaReference = maybeMediaReference { + if let message = messages.first, case let .message(text, attributes, _, maybeMediaReference, _, _, _) = message, let mediaReference = maybeMediaReference { self.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in var entities: [MessageTextEntity] = [] for attribute in attributes { @@ -10681,7 +10963,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - let inputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: presentationInterfaceState, isCaption: true, presentController: { _ in }) + let inputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: presentationInterfaceState, isCaption: true, presentController: { _ in }, makeEntityInputView: { [weak self] in + guard let strongSelf = self else { + return nil + } + + return EntityInputView(context: strongSelf.context, isDark: true, isSecret: strongSelf.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat) + }) inputPanelNode.interfaceInteraction = interfaceInteraction inputPanelNode.effectivePresentationInterfaceState = { return presentationInterfaceState @@ -10759,8 +11047,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -10916,7 +11204,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let currentFilesController = Atomic(value: nil) let currentLocationController = Atomic(value: nil) - let attachmentController = AttachmentController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: strongSelf.chatLocation, buttons: buttons, initialButton: initialButton) + let attachmentController = AttachmentController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: strongSelf.chatLocation, buttons: buttons, initialButton: initialButton, makeEntityInputView: { [weak self] in + guard let strongSelf = self else { + return nil + } + return EntityInputView(context: strongSelf.context, isDark: false, isSecret: strongSelf.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat) + }) attachmentController.requestController = { [weak self, weak attachmentController] type, completion in guard let strongSelf = self else { return @@ -10962,7 +11255,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { return } - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages([message])) |> deliverOnMainQueue).start(next: { [weak self] _ in if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages { @@ -10999,9 +11292,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -11032,7 +11327,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - textEnqueueMessage = .message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) } if peers.count > 1 { var enqueueMessages: [EnqueueMessage] = [] @@ -11064,12 +11359,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) enqueueMessages.append(message) } } @@ -11123,6 +11420,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -11133,7 +11432,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let textEnqueueMessage = textEnqueueMessage { enqueueMessages.append(textEnqueueMessage) } - enqueueMessages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) + enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)) } else { let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in @@ -11146,6 +11445,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -11156,7 +11457,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let textEnqueueMessage = textEnqueueMessage { enqueueMessages.append(textEnqueueMessage) } - enqueueMessages.append(.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) + enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)) strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)) } }), completed: nil, cancelled: nil) @@ -11364,8 +11665,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11462,8 +11763,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11588,7 +11889,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil) messages.append(message) } if let _ = groupingKey, messages.count % 10 == 0 { @@ -11602,6 +11903,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -11672,8 +11975,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } controller.presentStickers = { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11769,8 +12072,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G })) controller.presentStickers = { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11816,8 +12119,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11873,8 +12176,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G })) controller.presentStickers = { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -11914,9 +12217,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -11964,12 +12269,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) enqueueMessages.append(message) } } @@ -12023,12 +12330,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) strongSelf.sendMessages([message]) } else { let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in @@ -12041,12 +12350,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, nil) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil) strongSelf.sendMessages([message]) } }), completed: nil, cancelled: nil) @@ -12363,6 +12674,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12371,6 +12684,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let message: EnqueueMessage = .message( text: "", attributes: [], + inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaPoll( pollId: MediaId(namespace: Namespaces.Media.LocalPoll, id: Int64.random(in: Int64.min ... Int64.max)), publicity: poll.publicity, @@ -12434,7 +12748,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = (self.context.engine.stickers.loadedStickerPack(reference: stickerPackReference, forceActualized: false) |> deliverOnMainQueue).start(next: { [weak self] stickerPack in if let strongSelf = self, case let .result(info, _, _) = stickerPack { - strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: file, title: info.title, text: strongSelf.presentationData.strings.Stickers_PremiumPackInfoText, undoText: strongSelf.presentationData.strings.Stickers_PremiumPackView), elevatedLayout: false, action: { [weak self] action in + strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: file, title: info.title, text: strongSelf.presentationData.strings.Stickers_PremiumPackInfoText, undoText: strongSelf.presentationData.strings.Stickers_PremiumPackView, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self, action == .undo { let _ = strongSelf.controllerInteraction?.openMessage(message, .default) } @@ -12490,7 +12804,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let value = value { self.present(UndoOverlayController(presentationData: self.presentationData, content: .dice(dice: dice, context: self.context, text: value, action: canSendMessagesToChat(self.presentationInterfaceState) ? self.presentationData.strings.Conversation_SendDice : nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState), action == .undo { - strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]) } return false }), in: .current) @@ -12513,9 +12827,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let defaultReplyMessageId = defaultReplyMessageId { switch message { - case let .message(text, attributes, mediaReference, replyToMessageId, localGroupingKey, correlationId): + case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId): if replyToMessageId == nil { - message = .message(text: text, attributes: attributes, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) + message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId) } case .forward: break @@ -12678,6 +12992,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12723,8 +13039,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self?.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil) }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.present(controller, in: .window(.root)) @@ -12749,6 +13065,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12765,6 +13083,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12788,11 +13108,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G fileAttributes.append(.ImageSize(size: PixelDimensions(size))) let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes) - let message = EnqueueMessage.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12817,6 +13139,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if self.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peerId, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting) { self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in var state = state state = state.updatedInterfaceState { interfaceState in @@ -12936,6 +13260,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) @@ -12944,8 +13270,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.sendMessages([updatedMessage]) } - }, displaySlowmodeTooltip: { [weak self] node, rect in - self?.interfaceInteraction?.displaySlowmodeTooltip(node, rect) + }, displaySlowmodeTooltip: { [weak self] view, rect in + self?.interfaceInteraction?.displaySlowmodeTooltip(view, rect) }, presentSchedulePicker: { [weak self] done in if let strongSelf = self { strongSelf.presentScheduleTimePicker(completion: { [weak self] time in @@ -13045,13 +13371,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, usedCorrelationId ? correlationId : nil) - strongSelf.sendMessages([.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)]) + strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId)]) strongSelf.recorderFeedback?.tap() strongSelf.recorderFeedback = nil @@ -13131,7 +13459,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let _ = self.presentationInterfaceState.slowmodeState, !isScheduledMessages { if let rect = self.chatDisplayNode.frameForInputActionButton() { - self.interfaceInteraction?.displaySlowmodeTooltip(self.chatDisplayNode, rect) + self.interfaceInteraction?.displaySlowmodeTooltip(self.chatDisplayNode.view, rect) } return } @@ -13140,13 +13468,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in if let strongSelf = self { + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { $0.updatedRecordedMediaPreview(nil).updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } }) } }, nil) - let messages: [EnqueueMessage] = [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] + let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)] let transformedMessages: [EnqueueMessage] if let silentPosting = silentPosting { @@ -14049,7 +14379,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } } } @@ -14540,7 +14870,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G Queue.mainQueue().async { unblockingPeer.set(false) if let strongSelf = self, restartBot { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() } } })).start()) @@ -14821,8 +15151,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G default: break } - }, sendFile: nil, sendSticker: { [weak self] f, sourceNode, sourceRect in - return self?.interfaceInteraction?.sendSticker(f, true, sourceNode, sourceRect) ?? false + }, sendFile: nil, sendSticker: { [weak self] f, sourceView, sourceRect in + return self?.interfaceInteraction?.sendSticker(f, true, sourceView, sourceRect, nil) ?? false }, requestMessageActionUrlAuth: { [weak self] subject in if case let .url(url) = subject { self?.controllerInteraction?.requestMessageActionUrlAuth(url, subject) @@ -15306,7 +15636,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let tooltipController = self.mediaRecordingModeTooltipController { tooltipController.updateContent(.text(text), animated: true, extendTimer: true) } else if let rect = rect { - let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize) + let tooltipController = TooltipController(content: .text(text), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, padding: 2.0) self.mediaRecordingModeTooltipController = tooltipController tooltipController.dismissed = { [weak self, weak tooltipController] _ in if let strongSelf = self, let tooltipController = tooltipController, strongSelf.mediaRecordingModeTooltipController === tooltipController { @@ -15327,7 +15657,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } self.sendingOptionsTooltipController?.dismiss() - let tooltipController = TooltipController(content: .text(self.presentationData.strings.Conversation_SendingOptionsTooltip), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, timeout: 3.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true) + let tooltipController = TooltipController(content: .text(self.presentationData.strings.Conversation_SendingOptionsTooltip), baseFontSize: self.presentationData.listsFontSize.baseDisplaySize, timeout: 3.0, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true, padding: 2.0) self.sendingOptionsTooltipController = tooltipController tooltipController.dismissed = { [weak self, weak tooltipController] _ in if let strongSelf = self, let tooltipController = tooltipController, strongSelf.sendingOptionsTooltipController === tooltipController { @@ -16003,6 +16333,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } + public func hintPlayNextOutgoingGift() { + self.controllerInteraction?.playNextOutgoingGift = true + } + private var effectiveNavigationController: NavigationController? { if let navigationController = self.navigationController as? NavigationController { return navigationController @@ -16059,7 +16393,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceRect = self.sourceRect return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceRect ?? sourceNode.bounds) + return (sourceNode.view, sourceRect ?? sourceNode.bounds) } else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index d950b8235e..75332b03d1 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -73,9 +73,9 @@ public final class ChatControllerInteraction { let toggleMessagesSelection: ([MessageId], Bool) -> Void let sendCurrentMessage: (Bool) -> Void let sendMessage: (String) -> Void - let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, ASDisplayNode, CGRect) -> Bool - let sendGif: (FileMediaReference, ASDisplayNode, CGRect, Bool, Bool) -> Bool - let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, Bool) -> Bool + let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool + let sendGif: (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool + let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool) -> Bool let requestMessageActionCallback: (MessageId, MemoryBuffer?, Bool, Bool) -> Void let requestMessageActionUrlAuth: (String, MessageActionUrlSubject) -> Void let activateSwitchInline: (PeerId?, String) -> Void @@ -122,7 +122,7 @@ public final class ChatControllerInteraction { let displayPollSolution: (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void let displayPsa: (String, ASDisplayNode) -> Void let displayDiceTooltip: (TelegramMediaDice) -> Void - let animateDiceSuccess: (Bool) -> Void + let animateDiceSuccess: (Bool, Bool) -> Void let displayPremiumStickerTooltip: (TelegramMediaFile, Message) -> Void let openPeerContextMenu: (Peer, MessageId?, ASDisplayNode, CGRect, ContextGesture?) -> Void let openMessageReplies: (MessageId, Bool, Bool) -> Void @@ -141,6 +141,7 @@ public final class ChatControllerInteraction { let requestMessageUpdate: (MessageId) -> Void let cancelInteractiveKeyboardGestures: () -> Void + let dismissTextInput: () -> Void var canPlayMedia: Bool = false var hiddenMedia: [MessageId: [Media]] = [:] @@ -159,6 +160,7 @@ public final class ChatControllerInteraction { var currentMessageWithLoadingReplyThread: MessageId? var updatedPresentationData: (initial: PresentationData, signal: Signal)? let presentationContext: ChatPresentationContext + var playNextOutgoingGift: Bool = false init( openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, @@ -176,9 +178,9 @@ public final class ChatControllerInteraction { toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, - sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, ASDisplayNode, CGRect) -> Bool, - sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect, Bool, Bool) -> Bool, - sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, Bool) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool, + sendGif: @escaping (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool, + sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, UIView, CGRect, Bool) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageActionUrlSubject) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, @@ -225,7 +227,7 @@ public final class ChatControllerInteraction { displayPollSolution: @escaping (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void, displayPsa: @escaping (String, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, - animateDiceSuccess: @escaping (Bool) -> Void, + animateDiceSuccess: @escaping (Bool, Bool) -> Void, displayPremiumStickerTooltip: @escaping (TelegramMediaFile, Message) -> Void, openPeerContextMenu: @escaping (Peer, MessageId?, ASDisplayNode, CGRect, ContextGesture?) -> Void, openMessageReplies: @escaping (MessageId, Bool, Bool) -> Void, @@ -243,6 +245,7 @@ public final class ChatControllerInteraction { openWebView: @escaping (String, String, Bool, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, + dismissTextInput: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings, @@ -330,6 +333,7 @@ public final class ChatControllerInteraction { self.openWebView = openWebView self.requestMessageUpdate = requestMessageUpdate self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures + self.dismissTextInput = dismissTextInput self.automaticMediaDownloadSettings = automaticMediaDownloadSettings diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 8394750b97..6464b2f84b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -18,6 +18,8 @@ import WallpaperBackgroundNode import GridMessageSelectionNode import SparseItemGrid import ChatPresentationInterfaceState +import ChatInputPanelContainer +import PremiumUI final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { let itemNode: OverlayMediaItemNode @@ -68,6 +70,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private weak var controller: ChatControllerImpl? let navigationBar: NavigationBar? + let statusBar: StatusBar? private var backgroundEffectNode: ASDisplayNode? private var containerBackgroundNode: ASImageNode? @@ -81,9 +84,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } + let contentContainerNode: ASDisplayNode + let contentDimNode: ASDisplayNode let backgroundNode: WallpaperBackgroundNode let historyNode: ChatHistoryListNode - //let historyScrollingArea: SparseDiscreteScrollingArea var blurredHistoryNode: ASImageNode? let historyNodeContainer: ASDisplayNode let loadingNode: ChatLoadingNode @@ -98,9 +102,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private var searchNavigationNode: ChatSearchNavigationContentNode? - let inputPanelContainerNode: SparseNode + private var navigationModalFrame: NavigationModalFrame? + + let inputPanelContainerNode: ChatInputPanelContainer + private let inputPanelClippingNode: SparseNode private let inputPanelBackgroundNode: NavigationBackgroundNode + private var intrinsicInputPanelBackgroundNodeSize: CGSize? private let inputPanelBackgroundSeparatorNode: ASDisplayNode + private var inputPanelBottomBackgroundSeparatorBaseOffset: CGFloat = 0.0 + private let inputPanelBottomBackgroundSeparatorNode: ASDisplayNode private var plainInputSeparatorAlpha: CGFloat? private var usePlainInputSeparator: Bool @@ -115,14 +125,20 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private var secondaryInputPanelNode: ChatInputPanelNode? private(set) var accessoryPanelNode: AccessoryPanelNode? private var inputContextPanelNode: ChatInputContextPanelNode? - private let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer + let inputContextPanelContainer: ChatControllerTitlePanelNodeContainer + private let inputContextOverTextPanelContainer: ChatControllerTitlePanelNodeContainer private var overlayContextPanelNode: ChatInputContextPanelNode? private var inputNode: ChatInputNode? private var disappearingNode: ChatInputNode? private(set) var textInputPanelNode: ChatTextInputPanelNode? + private var inputMediaNode: ChatMediaInputNode? + private var inputMediaNodeData: ChatEntityKeyboardInputNode.InputData? + private var inputMediaNodeDataPromise = Promise() + private var didInitializeInputMediaNodeDataPromise: Bool = false + private var inputMediaNodeDataDisposable: Disposable? let navigateButtons: ChatHistoryNavigationButtons @@ -234,21 +250,29 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private var onLayoutCompletions: [(ContainedViewLayoutTransition) -> Void] = [] - init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, chatPresentationInterfaceState: ChatPresentationInterfaceState, automaticMediaDownloadSettings: MediaAutoDownloadSettings, navigationBar: NavigationBar?, backgroundNode: WallpaperBackgroundNode, controller: ChatControllerImpl?) { + init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, subject: ChatControllerSubject?, controllerInteraction: ChatControllerInteraction, chatPresentationInterfaceState: ChatPresentationInterfaceState, automaticMediaDownloadSettings: MediaAutoDownloadSettings, navigationBar: NavigationBar?, statusBar: StatusBar?, backgroundNode: WallpaperBackgroundNode, controller: ChatControllerImpl?) { self.context = context self.chatLocation = chatLocation self.controllerInteraction = controllerInteraction self.chatPresentationInterfaceState = chatPresentationInterfaceState self.automaticMediaDownloadSettings = automaticMediaDownloadSettings self.navigationBar = navigationBar + self.statusBar = statusBar self.controller = controller self.backgroundNode = backgroundNode + self.contentContainerNode = ASDisplayNode() + self.contentDimNode = ASDisplayNode() + self.contentDimNode.isUserInteractionEnabled = false + self.contentDimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.2) + self.contentDimNode.alpha = 0.0 + self.titleAccessoryPanelContainer = ChatControllerTitlePanelNodeContainer() self.titleAccessoryPanelContainer.clipsToBounds = true self.inputContextPanelContainer = ChatControllerTitlePanelNodeContainer() + self.inputContextOverTextPanelContainer = ChatControllerTitlePanelNodeContainer() var source: ChatHistoryListSource if case let .forwardedMessages(messageIds, options) = subject { @@ -363,7 +387,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.loadingNode = ChatLoadingNode(theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, bubbleCorners: self.chatPresentationInterfaceState.bubbleCorners) - self.inputPanelContainerNode = SparseNode() + self.inputPanelContainerNode = ChatInputPanelContainer() + self.inputPanelClippingNode = SparseNode() + if case let .color(color) = self.chatPresentationInterfaceState.chatWallpaper, UIColor(rgb: color).isEqual(self.chatPresentationInterfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) { self.inputPanelBackgroundNode = NavigationBackgroundNode(color: self.chatPresentationInterfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) self.usePlainInputSeparator = true @@ -378,6 +404,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputPanel.panelSeparatorColor self.inputPanelBackgroundSeparatorNode.isLayerBacked = true + self.inputPanelBottomBackgroundSeparatorNode = ASDisplayNode() + self.inputPanelBottomBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputMediaPanel.panelSeparatorColor + self.inputPanelBottomBackgroundSeparatorNode.isLayerBacked = true + self.navigateButtons = ChatHistoryNavigationButtons(theme: self.chatPresentationInterfaceState.theme, dateTimeFormat: self.chatPresentationInterfaceState.dateTimeFormat) self.navigateButtons.accessibilityElementsHidden = true @@ -491,30 +521,46 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.verticalScrollIndicatorColor = UIColor(white: 0.5, alpha: 0.8) } self.historyNode.enableExtractedBackgrounds = true - //self.historyNode.verticalScrollIndicatorColor = .clear - self.addSubnode(self.backgroundNode) - self.addSubnode(self.historyNodeContainer) - - self.addSubnode(self.inputPanelContainerNode) - self.inputPanelContainerNode.addSubnode(self.inputPanelBackgroundNode) - self.inputPanelContainerNode.addSubnode(self.inputPanelBackgroundSeparatorNode) - - self.addSubnode(self.inputContextPanelContainer) - + self.addSubnode(self.contentContainerNode) + self.contentContainerNode.addSubnode(self.backgroundNode) + self.contentContainerNode.addSubnode(self.historyNodeContainer) + if let navigationBar = self.navigationBar { - self.addSubnode(navigationBar) + self.contentContainerNode.addSubnode(navigationBar) } + self.inputPanelContainerNode.expansionUpdated = { [weak self] transition in + guard let strongSelf = self else { + return + } + + if transition.isAnimated { + strongSelf.scheduleLayoutTransitionRequest(transition) + } else { + strongSelf.requestLayout(transition) + } + } + + self.addSubnode(self.inputContextPanelContainer) + self.addSubnode(self.inputPanelContainerNode) + self.addSubnode(self.inputContextOverTextPanelContainer) + + self.inputPanelContainerNode.addSubnode(self.inputPanelClippingNode) + self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundNode) + self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundSeparatorNode) + self.inputPanelBackgroundNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) + self.addSubnode(self.messageTransitionNode) - self.addSubnode(self.navigateButtons) - self.addSubnode(self.presentationContextMarker) + self.contentContainerNode.addSubnode(self.navigateButtons) + self.contentContainerNode.addSubnode(self.presentationContextMarker) + self.contentContainerNode.addSubnode(self.contentDimNode) self.navigationBar?.additionalContentNode.addSubnode(self.titleAccessoryPanelContainer) self.historyNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - self.textInputPanelNode = ChatTextInputPanelNode(presentationInterfaceState: chatPresentationInterfaceState, presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode), presentController: { [weak self] controller in + self.textInputPanelNode = ChatTextInputPanelNode(context: context, presentationInterfaceState: chatPresentationInterfaceState, presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode), presentController: { [weak self] controller in self?.interfaceInteraction?.presentController(controller, nil) }) self.textInputPanelNode?.storedInputLanguage = chatPresentationInterfaceState.interfaceState.inputLanguage @@ -553,12 +599,46 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.textInputPanelNode?.updateActivity = { [weak self] in self?.updateTypingActivity(true) } + self.textInputPanelNode?.toggleExpandMediaInput = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.inputPanelContainerNode.toggleIfEnabled() + } + + self.textInputPanelNode?.switchToTextInputIfNeeded = { [weak self] in + guard let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction else { + return + } + + if let inputNode = strongSelf.inputNode as? ChatEntityKeyboardInputNode, !inputNode.canSwitchToTextInputAutomatically { + return + } + + interfaceInteraction.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + switch state.inputMode { + case .media: + return (.text, state.keyboardButtonsMessage?.id) + default: + return (state.inputMode, state.keyboardButtonsMessage?.id) + } + }) + } + + self.inputMediaNodeDataDisposable = (self.inputMediaNodeDataPromise.get() + |> deliverOnMainQueue).start(next: { [weak self] value in + guard let strongSelf = self else { + return + } + strongSelf.inputMediaNodeData = value + }) } deinit { self.interactiveEmojisDisposable?.dispose() self.openStickersDisposable?.dispose() self.displayVideoUnmuteTipDisposable?.dispose() + self.inputMediaNodeDataDisposable?.dispose() } override func didLoad() { @@ -687,6 +767,22 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } else { transition = protoTransition } + + if let statusBar = self.statusBar { + switch self.chatPresentationInterfaceState.mode { + case .standard: + if self.inputPanelContainerNode.expansionFraction > 0.3 { + statusBar.updateStatusBarStyle(.White, animated: true) + } else { + statusBar.updateStatusBarStyle(self.chatPresentationInterfaceState.theme.rootController.statusBarStyle.style, animated: true) + } + self.controller?.deferScreenEdgeGestures = [] + case .overlay: + self.controller?.deferScreenEdgeGestures = [.top] + case .inline: + statusBar.statusBarStyle = .Ignore + } + } var previousListBottomInset: CGFloat? if !self.historyNode.frame.isEmpty { @@ -695,6 +791,67 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.messageTransitionNode.frame = CGRect(origin: CGPoint(), size: layout.size) + self.contentContainerNode.frame = CGRect(origin: CGPoint(), size: layout.size) + + let visibleRootModalDismissProgress: CGFloat = 1.0 - self.inputPanelContainerNode.expansionFraction + if self.inputPanelContainerNode.expansionFraction != 0.0 { + let navigationModalFrame: NavigationModalFrame + var animateFromFraction: CGFloat? + if let current = self.navigationModalFrame { + navigationModalFrame = current + } else { + animateFromFraction = 1.0 + navigationModalFrame = NavigationModalFrame() + self.navigationModalFrame = navigationModalFrame + self.insertSubnode(navigationModalFrame, aboveSubnode: self.contentContainerNode) + } + if transition.isAnimated, let animateFromFraction = animateFromFraction, animateFromFraction != 1.0 - self.inputPanelContainerNode.expansionFraction { + navigationModalFrame.update(layout: layout, transition: .immediate) + navigationModalFrame.updateDismissal(transition: .immediate, progress: animateFromFraction, additionalProgress: 0.0, completion: {}) + } + navigationModalFrame.update(layout: layout, transition: transition) + navigationModalFrame.updateDismissal(transition: transition, progress: 1.0 - self.inputPanelContainerNode.expansionFraction, additionalProgress: 0.0, completion: {}) + + self.inputPanelClippingNode.clipsToBounds = true + transition.updateCornerRadius(node: self.inputPanelClippingNode, cornerRadius: self.inputPanelContainerNode.expansionFraction * 10.0) + } else { + if let navigationModalFrame = self.navigationModalFrame { + self.navigationModalFrame = nil + navigationModalFrame.updateDismissal(transition: transition, progress: 1.0, additionalProgress: 0.0, completion: { [weak navigationModalFrame] in + navigationModalFrame?.removeFromSupernode() + }) + } + self.inputPanelClippingNode.clipsToBounds = true + transition.updateCornerRadius(node: self.inputPanelClippingNode, cornerRadius: 0.0, completion: { [weak self] completed in + guard let strongSelf = self, completed else { + return + } + //strongSelf.inputPanelClippingNode.clipsToBounds = false + let _ = strongSelf + let _ = completed + }) + } + + transition.updateAlpha(node: self.contentDimNode, alpha: self.inputPanelContainerNode.expansionFraction) + + var topInset: CGFloat = 0.0 + if let statusBarHeight = layout.statusBarHeight { + topInset += statusBarHeight + } + + let maxScale: CGFloat + let maxOffset: CGFloat + maxScale = (layout.size.width - 16.0 * 2.0) / layout.size.width + maxOffset = (topInset - (layout.size.height - layout.size.height * maxScale) / 2.0) + + let scale = 1.0 * visibleRootModalDismissProgress + (1.0 - visibleRootModalDismissProgress) * maxScale + let offset = (1.0 - visibleRootModalDismissProgress) * maxOffset + transition.updateSublayerTransformScaleAndOffset(node: self.contentContainerNode, scale: scale, offset: CGPoint(x: 0.0, y: offset), beginWithCurrentState: true) + + if let navigationModalFrame = self.navigationModalFrame { + navigationModalFrame.update(layout: layout, transition: transition) + } + self.scheduledLayoutTransitionRequest = nil if case .overlay = self.chatPresentationInterfaceState.mode { if self.backgroundEffectNode == nil { @@ -763,10 +920,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let containerNode = self.containerNode { self.containerNode = nil containerNode.removeFromSupernode() - self.insertSubnode(self.backgroundNode, at: 0) - self.insertSubnode(self.historyNodeContainer, aboveSubnode: self.backgroundNode) + self.contentContainerNode.insertSubnode(self.backgroundNode, at: 0) + self.contentContainerNode.insertSubnode(self.historyNodeContainer, aboveSubnode: self.backgroundNode) if let restrictedNode = self.restrictedNode { - self.insertSubnode(restrictedNode, aboveSubnode: self.historyNodeContainer) + self.contentContainerNode.insertSubnode(restrictedNode, aboveSubnode: self.historyNodeContainer) } self.navigationBar?.isHidden = false } @@ -783,7 +940,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { wasDraggingKeyboard = true } var wasDraggingInputNode = false - if let derivedLayoutState = self.derivedLayoutState, let inputNodeHeight = derivedLayoutState.inputNodeHeight, !inputNodeHeight.isZero, let upperInputPositionBound = derivedLayoutState.upperInputPositionBound { + if let derivedLayoutState = self.derivedLayoutState, let inputNodeHeight = derivedLayoutState.inputNodeHeight, !inputNodeHeight.isZero, let upperInputPositionBound = derivedLayoutState.upperInputPositionBound { let normalizedHeight = max(0.0, layout.size.height - upperInputPositionBound) if normalizedHeight < inputNodeHeight { wasDraggingInputNode = true @@ -829,7 +986,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var titleAccessoryPanelHeight: CGFloat? var titleAccessoryPanelBackgroundHeight: CGFloat? var extraTransition = transition - if let titleAccessoryPanelNode = titlePanelForChatPresentationInterfaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.titleAccessoryPanelNode, interfaceInteraction: self.interfaceInteraction) { + if let titleAccessoryPanelNode = titlePanelForChatPresentationInterfaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.titleAccessoryPanelNode, controllerInteraction: self.controllerInteraction, interfaceInteraction: self.interfaceInteraction) { if self.titleAccessoryPanelNode != titleAccessoryPanelNode { dismissedTitleAccessoryPanelNode = self.titleAccessoryPanelNode self.titleAccessoryPanelNode = titleAccessoryPanelNode @@ -866,7 +1023,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if self.chatImportStatusPanel != importStatusPanelNode { dismissedImportStatusPanelNode = self.chatImportStatusPanel self.chatImportStatusPanel = importStatusPanelNode - self.addSubnode(importStatusPanelNode) + self.contentContainerNode.addSubnode(importStatusPanelNode) } importStatusPanelHeight = importStatusPanelNode.update(context: self.context, progress: CGFloat(importState.progress), presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: self.chatPresentationInterfaceState.theme, wallpaper: self.chatPresentationInterfaceState.chatWallpaper), fontSize: self.chatPresentationInterfaceState.fontSize, strings: self.chatPresentationInterfaceState.strings, dateTimeFormat: self.chatPresentationInterfaceState.dateTimeFormat, nameDisplayOrder: self.chatPresentationInterfaceState.nameDisplayOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: PresentationChatBubbleCorners(mainRadius: 0.0, auxiliaryRadius: 0.0, mergeBubbleCorners: false)), width: layout.size.width) @@ -883,15 +1040,169 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputPanelNodeBaseHeight += secondaryInputPanelNode.minimalHeight(interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) } - let maximumInputNodeHeight = layout.size.height - max(navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0), layout.safeInsets.top) - inputPanelNodeBaseHeight + let previewing: Bool + if case .standard(true) = self.chatPresentationInterfaceState.mode { + previewing = true + } else { + previewing = false + } + + let inputNodeForState = inputNodeForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentNode: self.inputNode, interfaceInteraction: self.interfaceInteraction, inputMediaNode: self.inputMediaNode, controllerInteraction: self.controllerInteraction, inputPanelNode: self.inputPanelNode, makeMediaInputNode: { + return self.makeMediaInputNode() + }) + + var insets: UIEdgeInsets + var inputPanelBottomInsetTerm: CGFloat = 0.0 + if let inputNodeForState = inputNodeForState { + if !self.inputPanelContainerNode.stableIsExpanded && inputNodeForState.adjustLayoutForHiddenInput { + inputNodeForState.hideInput = false + inputNodeForState.adjustLayoutForHiddenInput = false + } + + insets = layout.insets(options: []) + inputPanelBottomInsetTerm = max(insets.bottom, layout.standardInputHeight) + } else { + insets = layout.insets(options: [.input]) + } + + if case .overlay = self.chatPresentationInterfaceState.mode { + insets.top = 44.0 + } else { + insets.top += navigationBarHeight + } + + var inputPanelSize: CGSize? + var immediatelyLayoutInputPanelAndAnimateAppearance = false + var secondaryInputPanelSize: CGSize? + var immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = false + var inputPanelNodeHandlesTransition = false + + var dismissedInputPanelNode: ASDisplayNode? + var dismissedSecondaryInputPanelNode: ASDisplayNode? + var dismissedAccessoryPanelNode: AccessoryPanelNode? + var dismissedInputContextPanelNode: ChatInputContextPanelNode? + var dismissedOverlayContextPanelNode: ChatInputContextPanelNode? + + let inputPanelNodes = inputPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.inputPanelNode, currentSecondaryPanel: self.secondaryInputPanelNode, textInputPanelNode: self.textInputPanelNode, interfaceInteraction: self.interfaceInteraction) + + let inputPanelBottomInset = max(insets.bottom, inputPanelBottomInsetTerm) + + if let inputPanelNode = inputPanelNodes.primary, !previewing { + if inputPanelNode !== self.inputPanelNode { + if let inputTextPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { + if inputTextPanelNode.isFocused { + self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + } + let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0) + } + if let prevInputPanelNode = self.inputPanelNode, inputPanelNode.canHandleTransition(from: prevInputPanelNode) { + inputPanelNodeHandlesTransition = true + inputPanelNode.removeFromSupernode() + inputPanelNode.prevInputPanelNode = prevInputPanelNode + inputPanelNode.addSubnode(prevInputPanelNode) + } else { + dismissedInputPanelNode = self.inputPanelNode + } + let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0) + inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) + self.inputPanelNode = inputPanelNode + if inputPanelNode.supernode !== self { + immediatelyLayoutInputPanelAndAnimateAppearance = true + self.inputPanelClippingNode.insertSubnode(inputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) + } + } else { + let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset - 120.0, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0) + inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) + } + } else { + dismissedInputPanelNode = self.inputPanelNode + self.inputPanelNode = nil + } + + if let secondaryInputPanelNode = inputPanelNodes.secondary, !previewing { + if secondaryInputPanelNode !== self.secondaryInputPanelNode { + dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode + let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0) + secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) + self.secondaryInputPanelNode = secondaryInputPanelNode + if secondaryInputPanelNode.supernode == nil { + immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = true + self.inputPanelClippingNode.insertSubnode(secondaryInputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) + } + } else { + let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - inputPanelBottomInset, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: self.inputPanelContainerNode.expansionFraction == 1.0) + secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) + } + } else { + dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode + self.secondaryInputPanelNode = nil + } + + var accessoryPanelSize: CGSize? + var immediatelyLayoutAccessoryPanelAndAnimateAppearance = false + if let accessoryPanelNode = accessoryPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.accessoryPanelNode, chatControllerInteraction: self.controllerInteraction, interfaceInteraction: self.interfaceInteraction) { + accessoryPanelSize = accessoryPanelNode.measure(CGSize(width: layout.size.width, height: layout.size.height)) + + accessoryPanelNode.updateState(size: layout.size, inset: layout.safeInsets.left, interfaceState: self.chatPresentationInterfaceState) + + if accessoryPanelNode !== self.accessoryPanelNode { + dismissedAccessoryPanelNode = self.accessoryPanelNode + self.accessoryPanelNode = accessoryPanelNode + + if let inputPanelNode = self.inputPanelNode { + self.inputPanelClippingNode.insertSubnode(accessoryPanelNode, belowSubnode: inputPanelNode) + } else { + self.inputPanelClippingNode.insertSubnode(accessoryPanelNode, aboveSubnode: self.inputPanelBackgroundNode) + } + accessoryPanelNode.animateIn() + + accessoryPanelNode.dismiss = { [weak self, weak accessoryPanelNode] in + if let strongSelf = self, let accessoryPanelNode = accessoryPanelNode, strongSelf.accessoryPanelNode === accessoryPanelNode { + if let _ = accessoryPanelNode as? ReplyAccessoryPanelNode { + strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedReplyMessageId(nil) }) + } else if let _ = accessoryPanelNode as? ForwardAccessoryPanelNode { + strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil) }) + } else if let _ = accessoryPanelNode as? EditAccessoryPanelNode { + strongSelf.interfaceInteraction?.setupEditMessage(nil, { _ in }) + } else if let _ = accessoryPanelNode as? WebpagePreviewAccessoryPanelNode { + strongSelf.dismissUrlPreview() + } + } + } + + immediatelyLayoutAccessoryPanelAndAnimateAppearance = true + } + } else if let accessoryPanelNode = self.accessoryPanelNode { + dismissedAccessoryPanelNode = accessoryPanelNode + self.accessoryPanelNode = nil + } + + var maximumInputNodeHeight = layout.size.height - max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top) - 10.0 + if let inputPanelSize = inputPanelSize { + if let inputNode = self.inputNode, inputNode.hideInput, !inputNode.adjustLayoutForHiddenInput { + maximumInputNodeHeight -= inputPanelNodeBaseHeight + } else { + maximumInputNodeHeight -= inputPanelSize.height + } + } + if let secondaryInputPanelSize = secondaryInputPanelSize { + maximumInputNodeHeight -= secondaryInputPanelSize.height + } + if let accessoryPanelSize = accessoryPanelSize { + maximumInputNodeHeight -= accessoryPanelSize.height + } var dismissedInputNode: ChatInputNode? + var dismissedInputNodeInputBackgroundExtension: CGFloat = 0.0 + var dismissedInputNodeExternalTopPanelContainer: UIView? var immediatelyLayoutInputNodeAndAnimateAppearance = false var inputNodeHeightAndOverflow: (CGFloat, CGFloat)? - if let inputNode = inputNodeForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentNode: self.inputNode, interfaceInteraction: self.interfaceInteraction, inputMediaNode: self.inputMediaNode, controllerInteraction: self.controllerInteraction, inputPanelNode: self.inputPanelNode) { - if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { - if inputPanelNode.isFocused { - self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + if let inputNode = inputNodeForState { + if self.inputMediaNode != nil { + if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { + if inputPanelNode.isFocused { + self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + } } } if let inputMediaNode = inputNode as? ChatMediaInputNode, self.inputMediaNode == nil { @@ -901,20 +1212,71 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } if self.inputNode != inputNode { + inputNode.topBackgroundExtensionUpdated = { [weak self] transition in + self?.updateInputPanelBackgroundExtension(transition: transition) + } + inputNode.hideInputUpdated = { [weak self] transition in + guard let strongSelf = self else { + return + } + let applyAutocorrection = strongSelf.inputNode?.hideInput ?? false + + strongSelf.updateInputPanelBackgroundExpansion(transition: transition) + + if applyAutocorrection, let textInputPanelNode = strongSelf.textInputPanelNode { + if let textInputNode = textInputPanelNode.textInputNode, textInputNode.isFirstResponder() { + Keyboard.applyAutocorrection(textView: textInputNode.textView) + } + } + } + dismissedInputNode = self.inputNode + if let inputNode = self.inputNode { + dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension + } + dismissedInputNodeExternalTopPanelContainer = self.inputNode?.externalTopPanelContainer self.inputNode = inputNode inputNode.alpha = 1.0 inputNode.layer.removeAnimation(forKey: "opacity") immediatelyLayoutInputNodeAndAnimateAppearance = true - if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { - self.inputPanelContainerNode.insertSubnode(inputNode, aboveSubnode: inputPanelNode) + + if self.inputMediaNode != nil { + if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelClippingNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) + } else { + self.inputPanelClippingNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } } else { - self.inputPanelContainerNode.insertSubnode(inputNode, aboveSubnode: self.inputPanelBackgroundNode) + self.inputPanelClippingNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } + + if let externalTopPanelContainer = inputNode.externalTopPanelContainer { + if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelClippingNode.view.insertSubview(externalTopPanelContainer, belowSubview: inputPanelNode.view) + } else { + self.inputPanelClippingNode.view.addSubview(externalTopPanelContainer) + } } } - inputNodeHeightAndOverflow = inputNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, standardInputHeight: layout.standardInputHeight, inputHeight: layout.inputHeight ?? 0.0, maximumHeight: maximumInputNodeHeight, inputPanelHeight: inputPanelNodeBaseHeight, transition: immediatelyLayoutInputNodeAndAnimateAppearance ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: layout.deviceMetrics, isVisible: self.isInFocus) + + if inputNode.hideInput, inputNode.adjustLayoutForHiddenInput, let inputPanelSize = inputPanelSize { + maximumInputNodeHeight += inputPanelSize.height + } + + let inputHeight = layout.standardInputHeight + self.inputPanelContainerNode.expansionFraction * (maximumInputNodeHeight - layout.standardInputHeight) + + let heightAndOverflow = inputNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, standardInputHeight: inputHeight, inputHeight: layout.inputHeight ?? 0.0, maximumHeight: maximumInputNodeHeight, inputPanelHeight: inputPanelNodeBaseHeight, transition: immediatelyLayoutInputNodeAndAnimateAppearance ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: layout.deviceMetrics, isVisible: self.isInFocus, isExpanded: self.inputPanelContainerNode.stableIsExpanded) + + let boundedHeight = min(heightAndOverflow.0, layout.standardInputHeight) + + inputNodeHeightAndOverflow = ( + boundedHeight, + inputNode.followsDefaultHeight ? max(0.0, inputHeight - boundedHeight) : 0.0 + ) } else if let inputNode = self.inputNode { dismissedInputNode = inputNode + dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension + dismissedInputNodeExternalTopPanelContainer = inputNode.externalTopPanelContainer self.inputNode = nil } @@ -927,20 +1289,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - var insets: UIEdgeInsets var bottomOverflowOffset: CGFloat = 0.0 if let effectiveInputNodeHeight = effectiveInputNodeHeight, let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { - insets = layout.insets(options: []) insets.bottom = max(effectiveInputNodeHeight, insets.bottom) bottomOverflowOffset = inputNodeHeightAndOverflow.1 - } else { - insets = layout.insets(options: [.input]) - } - - if case .overlay = self.chatPresentationInterfaceState.mode { - insets.top = 44.0 - } else { - insets.top += navigationBarHeight } var wrappingInsets = UIEdgeInsets() @@ -955,19 +1307,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - var dismissedInputPanelNode: ASDisplayNode? - var dismissedSecondaryInputPanelNode: ASDisplayNode? - var dismissedAccessoryPanelNode: AccessoryPanelNode? - var dismissedInputContextPanelNode: ChatInputContextPanelNode? - var dismissedOverlayContextPanelNode: ChatInputContextPanelNode? - - let previewing: Bool - if case .standard(true) = self.chatPresentationInterfaceState.mode { - previewing = true - } else { - previewing = false - } - var isSelectionEnabled = true if previewing { isSelectionEnabled = false @@ -975,73 +1314,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { isSelectionEnabled = false } self.historyNode.isSelectionGestureEnabled = isSelectionEnabled - - var inputPanelSize: CGSize? - var immediatelyLayoutInputPanelAndAnimateAppearance = false - var secondaryInputPanelSize: CGSize? - var immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = false - var inputPanelNodeHandlesTransition = false - - let inputPanelNodes = inputPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.inputPanelNode, currentSecondaryPanel: self.secondaryInputPanelNode, textInputPanelNode: self.textInputPanelNode, interfaceInteraction: self.interfaceInteraction) - - if let inputPanelNode = inputPanelNodes.primary, !previewing { - if inputPanelNode !== self.inputPanelNode { - if let inputTextPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { - if inputTextPanelNode.isFocused { - self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) - } - let _ = inputTextPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) - } - if let prevInputPanelNode = self.inputPanelNode, inputPanelNode.canHandleTransition(from: prevInputPanelNode) { - inputPanelNodeHandlesTransition = true - inputPanelNode.removeFromSupernode() - inputPanelNode.prevInputPanelNode = prevInputPanelNode - inputPanelNode.addSubnode(prevInputPanelNode) - } else { - dismissedInputPanelNode = self.inputPanelNode - } - let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: false, transition: inputPanelNode.supernode !== self ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) - inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) - self.inputPanelNode = inputPanelNode - if inputPanelNode.supernode !== self { - immediatelyLayoutInputPanelAndAnimateAppearance = true - self.inputPanelContainerNode.insertSubnode(inputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) - } - } else { - let inputPanelHeight = inputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom - 120.0, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) - inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) - } - } else { - dismissedInputPanelNode = self.inputPanelNode - self.inputPanelNode = nil - } - - if let secondaryInputPanelNode = inputPanelNodes.secondary, !previewing { - if secondaryInputPanelNode !== self.secondaryInputPanelNode { - dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode - let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) - secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) - self.secondaryInputPanelNode = secondaryInputPanelNode - if secondaryInputPanelNode.supernode == nil { - immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = true - self.inputPanelContainerNode.insertSubnode(secondaryInputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) - } - } else { - let inputPanelHeight = secondaryInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: layout.additionalInsets, maxHeight: layout.size.height - insets.top - insets.bottom, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) - secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) - } - } else { - dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode - self.secondaryInputPanelNode = nil - } if let inputMediaNode = self.inputMediaNode, inputMediaNode != self.inputNode { - let _ = inputMediaNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, standardInputHeight: layout.standardInputHeight, inputHeight: layout.inputHeight ?? 0.0, maximumHeight: maximumInputNodeHeight, inputPanelHeight: inputPanelSize?.height ?? 0.0, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: layout.deviceMetrics, isVisible: false) + let _ = inputMediaNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, standardInputHeight: layout.standardInputHeight, inputHeight: layout.inputHeight ?? 0.0, maximumHeight: maximumInputNodeHeight, inputPanelHeight: inputPanelSize?.height ?? 0.0, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: layout.deviceMetrics, isVisible: false, isExpanded: self.inputPanelContainerNode.stableIsExpanded) } transition.updateFrame(node: self.titleAccessoryPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: 66.0))) transition.updateFrame(node: self.inputContextPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))) + transition.updateFrame(node: self.inputContextOverTextPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: layout.size.height))) var titleAccessoryPanelFrame: CGRect? if let _ = self.titleAccessoryPanelNode, let panelHeight = titleAccessoryPanelHeight { @@ -1057,7 +1338,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { insets.top += panelHeight } - let contentBounds = CGRect(x: 0.0, y: -bottomOverflowOffset, width: layout.size.width - wrappingInsets.left - wrappingInsets.right, height: layout.size.height - wrappingInsets.top - wrappingInsets.bottom) + let contentBounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width - wrappingInsets.left - wrappingInsets.right, height: layout.size.height - wrappingInsets.top - wrappingInsets.bottom) if let backgroundEffectNode = self.backgroundEffectNode { transition.updateFrame(node: backgroundEffectNode, frame: CGRect(origin: CGPoint(), size: layout.size)) @@ -1084,52 +1365,18 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) - var accessoryPanelSize: CGSize? - var immediatelyLayoutAccessoryPanelAndAnimateAppearance = false - if let accessoryPanelNode = accessoryPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.accessoryPanelNode, interfaceInteraction: self.interfaceInteraction) { - accessoryPanelSize = accessoryPanelNode.measure(CGSize(width: layout.size.width, height: layout.size.height)) - - accessoryPanelNode.updateState(size: layout.size, inset: layout.safeInsets.left, interfaceState: self.chatPresentationInterfaceState) - - if accessoryPanelNode !== self.accessoryPanelNode { - dismissedAccessoryPanelNode = self.accessoryPanelNode - self.accessoryPanelNode = accessoryPanelNode - - if let inputPanelNode = self.inputPanelNode { - self.inputPanelContainerNode.insertSubnode(accessoryPanelNode, belowSubnode: inputPanelNode) - } else { - self.inputPanelContainerNode.insertSubnode(accessoryPanelNode, aboveSubnode: self.inputPanelBackgroundNode) - } - accessoryPanelNode.animateIn() - - accessoryPanelNode.dismiss = { [weak self, weak accessoryPanelNode] in - if let strongSelf = self, let accessoryPanelNode = accessoryPanelNode, strongSelf.accessoryPanelNode === accessoryPanelNode { - if let _ = accessoryPanelNode as? ReplyAccessoryPanelNode { - strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedReplyMessageId(nil) }) - } else if let _ = accessoryPanelNode as? ForwardAccessoryPanelNode { - strongSelf.requestUpdateChatInterfaceState(.animated(duration: 0.4, curve: .spring), false, { $0.withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil) }) - } else if let _ = accessoryPanelNode as? EditAccessoryPanelNode { - strongSelf.interfaceInteraction?.setupEditMessage(nil, { _ in }) - } else if let _ = accessoryPanelNode as? WebpagePreviewAccessoryPanelNode { - strongSelf.dismissUrlPreview() - } - } - } - - immediatelyLayoutAccessoryPanelAndAnimateAppearance = true - } - } else if let accessoryPanelNode = self.accessoryPanelNode { - dismissedAccessoryPanelNode = accessoryPanelNode - self.accessoryPanelNode = nil - } - var immediatelyLayoutInputContextPanelAndAnimateAppearance = false - if let inputContextPanelNode = inputContextPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.inputContextPanelNode, controllerInteraction: self.controllerInteraction, interfaceInteraction: self.interfaceInteraction) { + if let inputContextPanelNode = inputContextPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.inputContextPanelNode, controllerInteraction: self.controllerInteraction, interfaceInteraction: self.interfaceInteraction, chatPresentationContext: self.controllerInteraction.presentationContext) { if inputContextPanelNode !== self.inputContextPanelNode { dismissedInputContextPanelNode = self.inputContextPanelNode self.inputContextPanelNode = inputContextPanelNode - - self.inputContextPanelContainer.addSubnode(inputContextPanelNode) + switch inputContextPanelNode.placement { + case .overPanels: + self.inputContextPanelContainer.addSubnode(inputContextPanelNode) + case .overTextInput: + inputContextPanelNode.view.disablesInteractiveKeyboardGestureRecognizer = true + self.inputContextOverTextPanelContainer.addSubnode(inputContextPanelNode) + } immediatelyLayoutInputContextPanelAndAnimateAppearance = true } } else if let inputContextPanelNode = self.inputContextPanelNode { @@ -1138,12 +1385,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } var immediatelyLayoutOverlayContextPanelAndAnimateAppearance = false - if let overlayContextPanelNode = chatOverlayContextPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.overlayContextPanelNode, interfaceInteraction: self.interfaceInteraction) { + if let overlayContextPanelNode = chatOverlayContextPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.overlayContextPanelNode, interfaceInteraction: self.interfaceInteraction, chatPresentationContext: self.controllerInteraction.presentationContext) { if overlayContextPanelNode !== self.overlayContextPanelNode { dismissedOverlayContextPanelNode = self.overlayContextPanelNode self.overlayContextPanelNode = overlayContextPanelNode - self.addSubnode(overlayContextPanelNode) + self.contentContainerNode.addSubnode(overlayContextPanelNode) immediatelyLayoutOverlayContextPanelAndAnimateAppearance = true } } else if let overlayContextPanelNode = self.overlayContextPanelNode { @@ -1156,12 +1403,27 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var inputPanelFrame: CGRect? var secondaryInputPanelFrame: CGRect? + var inputPanelHideOffset: CGFloat = 0.0 + if let inputNode = self.inputNode, inputNode.hideInput { + if let inputPanelSize = inputPanelSize { + inputPanelHideOffset += -inputPanelSize.height + } + if let accessoryPanelSize = accessoryPanelSize { + inputPanelHideOffset += -accessoryPanelSize.height + } + } + if self.inputPanelNode != nil { inputPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - insets.bottom - bottomOverflowOffset - inputPanelsHeight - inputPanelSize!.height), size: CGSize(width: layout.size.width, height: inputPanelSize!.height)) + inputPanelFrame = inputPanelFrame!.offsetBy(dx: 0.0, dy: inputPanelHideOffset) if self.dismissedAsOverlay { inputPanelFrame!.origin.y = layout.size.height } - inputPanelsHeight += inputPanelSize!.height + if let inputNode = self.inputNode, inputNode.hideInput, !inputNode.adjustLayoutForHiddenInput { + inputPanelsHeight += inputPanelNodeBaseHeight + } else { + inputPanelsHeight += inputPanelSize!.height + } } if self.secondaryInputPanelNode != nil { @@ -1176,16 +1438,26 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if self.accessoryPanelNode != nil { assert(accessoryPanelSize != nil) accessoryPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomOverflowOffset - insets.bottom - inputPanelsHeight - accessoryPanelSize!.height), size: CGSize(width: layout.size.width, height: accessoryPanelSize!.height)) + accessoryPanelFrame = accessoryPanelFrame!.offsetBy(dx: 0.0, dy: inputPanelHideOffset) if self.dismissedAsOverlay { accessoryPanelFrame!.origin.y = layout.size.height } - inputPanelsHeight += accessoryPanelSize!.height + if let inputNode = self.inputNode, inputNode.hideInput { + } else { + inputPanelsHeight += accessoryPanelSize!.height + } } if self.dismissedAsOverlay { inputPanelsHeight = 0.0 } + if let inputNode = self.inputNode { + if inputNode.hideInput && inputNode.adjustLayoutForHiddenInput { + inputPanelsHeight = 0.0 + } + } + let inputBackgroundInset: CGFloat if cleanInsets.bottom < insets.bottom { inputBackgroundInset = 0.0 @@ -1296,7 +1568,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { expandedInputDimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5) expandedInputDimNode.alpha = 0.0 self.expandedInputDimNode = expandedInputDimNode - self.insertSubnode(expandedInputDimNode, aboveSubnode: self.historyNodeContainer) + self.contentContainerNode.insertSubnode(expandedInputDimNode, aboveSubnode: self.historyNodeContainer) transition.updateAlpha(node: expandedInputDimNode, alpha: 1.0) expandedInputDimNode.frame = exandedFrame transition.animatePositionAdditive(node: expandedInputDimNode, offset: CGPoint(x: 0.0, y: previousInputPanelOrigin.y - inputPanelOrigin)) @@ -1333,7 +1605,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) let navigateButtonsSize = self.navigateButtons.updateLayout(transition: transition) - var navigateButtonsFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - navigateButtonsSize.width - 6.0, y: layout.size.height - containerInsets.bottom - inputPanelsHeight - navigateButtonsSize.height - 6.0 - bottomOverflowOffset), size: navigateButtonsSize) + var navigateButtonsFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - navigateButtonsSize.width - 6.0, y: layout.size.height - containerInsets.bottom - inputPanelsHeight - navigateButtonsSize.height - 6.0), size: navigateButtonsSize) if case .overlay = self.chatPresentationInterfaceState.mode { navigateButtonsFrame = navigateButtonsFrame.offsetBy(dx: -8.0, dy: -8.0) } @@ -1343,7 +1615,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var apparentInputBackgroundFrame = inputBackgroundFrame var apparentNavigateButtonsFrame = navigateButtonsFrame if case let .media(_, maybeExpanded, _) = self.chatPresentationInterfaceState.inputMode, let expanded = maybeExpanded, case .search = expanded, let inputPanelFrame = inputPanelFrame { - let verticalOffset = -inputPanelFrame.height - 41.0 + let verticalOffset = -inputPanelFrame.height - 34.0 apparentInputPanelFrame = inputPanelFrame.offsetBy(dx: 0.0, dy: verticalOffset) apparentInputBackgroundFrame.size.height -= verticalOffset apparentInputBackgroundFrame.origin.y += verticalOffset @@ -1354,10 +1626,38 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { apparentNavigateButtonsFrame.origin.y -= 16.0 } + var isInputExpansionEnabled = false + if case .media = self.chatPresentationInterfaceState.inputMode { + isInputExpansionEnabled = true + } + let previousInputPanelBackgroundFrame = self.inputPanelBackgroundNode.frame transition.updateFrame(node: self.inputPanelContainerNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame) - self.inputPanelBackgroundNode.update(size: CGSize(width: apparentInputBackgroundFrame.size.width, height: apparentInputBackgroundFrame.size.height + 41.0 + 31.0), transition: transition) + self.inputPanelContainerNode.update(size: layout.size, scrollableDistance: max(0.0, maximumInputNodeHeight - layout.standardInputHeight), isExpansionEnabled: isInputExpansionEnabled, transition: transition) + transition.updatePosition(node: self.inputPanelClippingNode, position: CGRect(origin: apparentInputBackgroundFrame.origin, size: layout.size).center, beginWithCurrentState: true) + transition.updateBounds(node: self.inputPanelClippingNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: layout.size), beginWithCurrentState: true) + transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame, beginWithCurrentState: true) + + transition.updateFrame(node: self.contentDimNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: apparentInputBackgroundFrame.origin.y))) + + let intrinsicInputPanelBackgroundNodeSize = CGSize(width: apparentInputBackgroundFrame.size.width, height: apparentInputBackgroundFrame.size.height) + self.intrinsicInputPanelBackgroundNodeSize = intrinsicInputPanelBackgroundNodeSize + var inputPanelBackgroundExtension: CGFloat = 0.0 + if let inputNode = self.inputNode { + inputPanelBackgroundExtension = inputNode.topBackgroundExtension + } else { + inputPanelBackgroundExtension = dismissedInputNodeInputBackgroundExtension + } + + var inputPanelUpdateTransition = transition + if immediatelyLayoutInputNodeAndAnimateAppearance { + inputPanelUpdateTransition = .immediate + } + + self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition, beginWithCurrentState: true) + self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height + inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: UIScreenPixel)), beginWithCurrentState: true) + transition.updateFrame(node: self.inputPanelBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: CGSize(width: apparentInputBackgroundFrame.size.width, height: UIScreenPixel))) transition.updateFrame(node: self.navigateButtons, frame: apparentNavigateButtonsFrame) @@ -1431,14 +1731,24 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if immediatelyLayoutInputNodeAndAnimateAppearance { var adjustedForPreviousInputHeightFrame = inputNodeFrame var heightDifference = inputNodeHeight - previousInputHeight + var externalTopPanelContainerOffset: CGFloat = 0.0 if previousInputHeight.isLessThanOrEqualTo(cleanInsets.bottom) { - heightDifference = inputNodeHeight + heightDifference = inputNodeHeight - inputPanelBackgroundExtension + externalTopPanelContainerOffset = inputPanelBackgroundExtension } adjustedForPreviousInputHeightFrame.origin.y += heightDifference inputNode.frame = adjustedForPreviousInputHeightFrame transition.updateFrame(node: inputNode, frame: inputNodeFrame) + + if let externalTopPanelContainer = inputNode.externalTopPanelContainer { + externalTopPanelContainer.frame = CGRect(origin: adjustedForPreviousInputHeightFrame.offsetBy(dx: 0.0, dy: externalTopPanelContainerOffset).origin, size: CGSize(width: adjustedForPreviousInputHeightFrame.width, height: 0.0)) + transition.updateFrame(view: externalTopPanelContainer, frame: CGRect(origin: inputNodeFrame.origin, size: CGSize(width: inputNodeFrame.width, height: 0.0))) + } } else { transition.updateFrame(node: inputNode, frame: inputNodeFrame) + if let externalTopPanelContainer = inputNode.externalTopPanelContainer { + transition.updateFrame(view: externalTopPanelContainer, frame: CGRect(origin: inputNodeFrame.origin, size: CGSize(width: inputNodeFrame.width, height: 0.0))) + } } } @@ -1458,9 +1768,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) } - if let inputPanelNode = self.inputPanelNode, - let apparentInputPanelFrame = apparentInputPanelFrame, - !inputPanelNode.frame.equalTo(apparentInputPanelFrame) { + if let inputPanelNode = self.inputPanelNode, let apparentInputPanelFrame = apparentInputPanelFrame, !inputPanelNode.frame.equalTo(apparentInputPanelFrame) { if immediatelyLayoutInputPanelAndAnimateAppearance { inputPanelNode.frame = apparentInputPanelFrame.offsetBy(dx: 0.0, dy: apparentInputPanelFrame.height + previousInputPanelBackgroundFrame.maxY - apparentInputBackgroundFrame.maxY) inputPanelNode.alpha = 0.0 @@ -1628,6 +1936,24 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } else { targetY = layout.size.height } + + if let dismissedInputNodeExternalTopPanelContainer = dismissedInputNodeExternalTopPanelContainer { + transition.updateFrame(view: dismissedInputNodeExternalTopPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: targetY), size: CGSize(width: layout.size.width, height: 0.0)), force: true, completion: { [weak self, weak dismissedInputNodeExternalTopPanelContainer] completed in + if let strongSelf = self, let dismissedInputNodeExternalTopPanelContainer = dismissedInputNodeExternalTopPanelContainer { + if strongSelf.inputNode?.externalTopPanelContainer !== dismissedInputNodeExternalTopPanelContainer { + dismissedInputNodeExternalTopPanelContainer.alpha = 0.0 + dismissedInputNodeExternalTopPanelContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak dismissedInputNodeExternalTopPanelContainer] completed in + if completed, let strongSelf = self, let dismissedInputNodeExternalTopPanelContainer = dismissedInputNodeExternalTopPanelContainer { + if strongSelf.inputNode?.externalTopPanelContainer !== dismissedInputNodeExternalTopPanelContainer { + dismissedInputNodeExternalTopPanelContainer.removeFromSuperview() + } + } + }) + } + } + }) + } + transition.updateFrame(node: dismissedInputNode, frame: CGRect(origin: CGPoint(x: 0.0, y: targetY), size: CGSize(width: layout.size.width, height: max(insets.bottom, dismissedInputNode.bounds.size.height))), force: true, completion: { [weak self, weak dismissedInputNode] completed in if let dismissedInputNode = dismissedInputNode { if let strongSelf = self { @@ -1688,6 +2014,40 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { //self.notifyTransitionCompletionListeners(transition: transition) } + private func updateInputPanelBackgroundExtension(transition: ContainedViewLayoutTransition) { + guard let intrinsicInputPanelBackgroundNodeSize = self.intrinsicInputPanelBackgroundNodeSize else { + return + } + + var extensionValue: CGFloat = 0.0 + if let inputNode = self.inputNode { + extensionValue = inputNode.topBackgroundExtension + } + + self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + extensionValue), transition: transition) + transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBottomBackgroundSeparatorBaseOffset + extensionValue), size: CGSize(width: self.inputPanelBottomBackgroundSeparatorNode.bounds.width, height: UIScreenPixel)), beginWithCurrentState: true) + } + + private var storedHideInputExpanded: Bool? + + private func updateInputPanelBackgroundExpansion(transition: ContainedViewLayoutTransition) { + if let inputNode = self.inputNode { + if inputNode.hideInput && inputNode.adjustLayoutForHiddenInput { + self.storedHideInputExpanded = self.inputPanelContainerNode.expansionFraction == 1.0 + self.inputPanelContainerNode.expand() + } else { + if let storedHideInputExpanded = self.storedHideInputExpanded { + self.storedHideInputExpanded = nil + if !storedHideInputExpanded { + self.inputPanelContainerNode.collapse() + } + } + } + } + + self.requestLayout(transition) + } + private func notifyTransitionCompletionListeners(transition: ContainedViewLayoutTransition) { if !self.onLayoutCompletions.isEmpty { let onLayoutCompletions = self.onLayoutCompletions @@ -1700,14 +2060,34 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private func chatPresentationInterfaceStateRequiresInputFocus(_ state: ChatPresentationInterfaceState) -> Bool { switch state.inputMode { - case .text: - if state.interfaceState.selectionState != nil { - return false - } else { - return true - } - default: + case .text: + if state.interfaceState.selectionState != nil { return false + } else { + return true + } + case .media: + return true + default: + return false + } + } + + private final class EmptyInputView: UIView, UIInputViewAudioFeedback { + var enableInputClicksWhenVisible: Bool { + return true + } + } + + private let emptyInputView = EmptyInputView() + private func chatPresentationInterfaceStateInputView(_ state: ChatPresentationInterfaceState) -> UIView? { + switch state.inputMode { + case .text: + return nil + case .media: + return self.emptyInputView + default: + return nil } } @@ -1729,7 +2109,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.verticalScrollIndicatorColor = UIColor(white: 0.5, alpha: 0.8) - let updatedInputFocus = self.chatPresentationInterfaceStateRequiresInputFocus(self.chatPresentationInterfaceState) != self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) + var updatedInputFocus = self.chatPresentationInterfaceStateRequiresInputFocus(self.chatPresentationInterfaceState) != self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) + if self.chatPresentationInterfaceStateInputView(self.chatPresentationInterfaceState) !== self.chatPresentationInterfaceStateInputView(chatPresentationInterfaceState) { + updatedInputFocus = true + } + let updateInputTextState = self.chatPresentationInterfaceState.interfaceState.effectiveInputState != chatPresentationInterfaceState.interfaceState.effectiveInputState self.chatPresentationInterfaceState = chatPresentationInterfaceState @@ -1746,6 +2130,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } self.updatePlainInputSeparator(transition: .immediate) self.inputPanelBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputPanel.panelSeparatorColor + self.inputPanelBottomBackgroundSeparatorNode.backgroundColor = self.chatPresentationInterfaceState.theme.chat.inputMediaPanel.panelSeparatorColor self.backgroundNode.updateBubbleTheme(bubbleTheme: chatPresentationInterfaceState.theme, bubbleCorners: chatPresentationInterfaceState.bubbleCorners) } @@ -1840,8 +2225,22 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated) } + var waitForKeyboardLayout = false + if let textView = self.textInputPanelNode?.textInputNode?.textView { + let updatedInputView = self.chatPresentationInterfaceStateInputView(chatPresentationInterfaceState) + if textView.inputView !== updatedInputView { + textView.inputView = updatedInputView + if textView.isFirstResponder { + if self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) { + waitForKeyboardLayout = true + } + textView.reloadInputViews() + } + } + } + if updatedInputFocus { - if !self.ignoreUpdateHeight { + if !self.ignoreUpdateHeight && !waitForKeyboardLayout { self.scheduleLayoutTransitionRequest(layoutTransition) } @@ -1948,6 +2347,23 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.view.window?.endEditing(true) } + func dismissTextInput() { + self.view.window?.endEditing(true) + } + + func collapseInput() { + if self.inputPanelContainerNode.expansionFraction != 0.0 { + self.inputPanelContainerNode.collapse() + if let inputNode = self.inputNode { + inputNode.hideInput = false + inputNode.adjustLayoutForHiddenInput = false + if let inputNode = inputNode as? ChatEntityKeyboardInputNode { + inputNode.markInputCollapsed() + } + } + } + } + private func scheduleLayoutTransitionRequest(_ transition: ContainedViewLayoutTransition) { let requestId = self.scheduledLayoutTransitionRequestId self.scheduledLayoutTransitionRequestId += 1 @@ -1963,8 +2379,37 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.setNeedsLayout() } + private func makeMediaInputNode() -> ChatInputNode? { + guard let inputMediaNodeData = self.inputMediaNodeData else { + return nil + } + + var peerId: PeerId? + if case let .peer(id) = self.chatPresentationInterfaceState.chatLocation { + peerId = id + } + + let inputNode = ChatEntityKeyboardInputNode( + context: self.context, + currentInputData: inputMediaNodeData, + updatedInputData: self.inputMediaNodeDataPromise.get(), + defaultToEmojiTab: !self.chatPresentationInterfaceState.interfaceState.effectiveInputState.inputText.string.isEmpty, + controllerInteraction: self.controllerInteraction, + interfaceInteraction: self.interfaceInteraction, + chatPeerId: peerId + ) + + return inputNode + } + func loadInputPanels(theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { - if self.inputMediaNode == nil { + if !self.didInitializeInputMediaNodeDataPromise, let interfaceInteraction = self.interfaceInteraction { + self.didInitializeInputMediaNodeDataPromise = true + + self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction, chatPeerId: self.chatLocation.peerId)) + } + + if self.inputMediaNode == nil && !"".isEmpty { let peerId: PeerId? = self.chatPresentationInterfaceState.chatLocation.peerId let inputNode = ChatMediaInputNode(context: self.context, peerId: peerId, chatLocation: self.chatPresentationInterfaceState.chatLocation, controllerInteraction: self.controllerInteraction, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, theme: theme, strings: strings, fontSize: fontSize, gifPaneIsActiveUpdated: { [weak self] value in if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction { @@ -1987,11 +2432,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } self.inputMediaNode = inputNode if let (validLayout, _) = self.validLayout { - let _ = inputNode.updateLayout(width: validLayout.size.width, leftInset: validLayout.safeInsets.left, rightInset: validLayout.safeInsets.right, bottomInset: validLayout.intrinsicInsets.bottom, standardInputHeight: validLayout.standardInputHeight, inputHeight: validLayout.inputHeight ?? 0.0, maximumHeight: validLayout.standardInputHeight, inputPanelHeight: 44.0, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: validLayout.deviceMetrics, isVisible: false) + let _ = inputNode.updateLayout(width: validLayout.size.width, leftInset: validLayout.safeInsets.left, rightInset: validLayout.safeInsets.right, bottomInset: validLayout.intrinsicInsets.bottom, standardInputHeight: validLayout.standardInputHeight, inputHeight: validLayout.inputHeight ?? 0.0, maximumHeight: validLayout.standardInputHeight, inputPanelHeight: 44.0, transition: .immediate, interfaceState: self.chatPresentationInterfaceState, deviceMetrics: validLayout.deviceMetrics, isVisible: false, isExpanded: self.inputPanelContainerNode.stableIsExpanded) } - - self.textInputPanelNode?.loadTextInputNodeIfNeeded() } + + self.textInputPanelNode?.loadTextInputNodeIfNeeded() } func currentInputPanelFrame() -> CGRect? { @@ -2271,7 +2716,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let dropDimNode = ASDisplayNode() dropDimNode.backgroundColor = self.chatPresentationInterfaceState.theme.chatList.backgroundColor.withAlphaComponent(0.35) self.dropDimNode = dropDimNode - self.addSubnode(dropDimNode) + self.contentContainerNode.addSubnode(dropDimNode) if let (layout, _) = self.validLayout { dropDimNode.frame = CGRect(origin: CGPoint(), size: layout.size) dropDimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) @@ -2309,7 +2754,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let keyboardGestureBeginLocation = location let accessoryHeight = self.getWindowInputAccessoryHeight() - if let inputHeight = derivedLayoutState.inputNodeHeight, !inputHeight.isZero, keyboardGestureBeginLocation.y < validLayout.size.height - inputHeight - accessoryHeight { + if let inputHeight = derivedLayoutState.inputNodeHeight, !inputHeight.isZero, keyboardGestureBeginLocation.y < validLayout.size.height - inputHeight - accessoryHeight, !self.inputPanelContainerNode.stableIsExpanded { var enableGesture = true if let view = self.view.hitTest(location, with: nil) { if doesViewTreeDisableInteractiveTransitionGestureRecognizer(view) { @@ -2382,15 +2827,31 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } func openStickers() { - if let inputMediaNode = self.inputMediaNode, self.openStickersDisposable == nil { - self.openStickersDisposable = (inputMediaNode.ready - |> take(1) - |> deliverOnMainQueue).start(next: { [weak self] in - self?.openStickersDisposable = nil - self?.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) + if let inputMediaNode = self.inputMediaNode { + if self.openStickersDisposable == nil { + self.openStickersDisposable = (inputMediaNode.ready + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] in + self?.openStickersDisposable = nil + self?.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) + }) }) - }) + } + } else { + if self.openStickersDisposable == nil { + self.openStickersDisposable = (self.inputMediaNodeDataPromise.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let strongSelf = self else { + return + } + + strongSelf.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) + }) + }) + } } } @@ -2415,11 +2876,52 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let _ = effectivePresentationInterfaceState.slowmodeState, !isScheduledMessages && scheduleTime == nil { if let rect = self.frameForInputActionButton() { - self.interfaceInteraction?.displaySlowmodeTooltip(self, rect) + self.interfaceInteraction?.displaySlowmodeTooltip(self.view, rect) } return } + var messages: [EnqueueMessage] = [] + + let effectiveInputText = effectivePresentationInterfaceState.interfaceState.composeInputState.inputText + + var inlineStickers: [MediaId: Media] = [:] + var firstLockedPremiumEmoji: TelegramMediaFile? + effectiveInputText.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: effectiveInputText.length), using: { value, _, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + if let file = value.file { + inlineStickers[file.fileId] = file + if file.isPremiumEmoji && !self.chatPresentationInterfaceState.isPremium { + if firstLockedPremiumEmoji == nil { + firstLockedPremiumEmoji = file + } + } + } + } + }) + + if let firstLockedPremiumEmoji = firstLockedPremiumEmoji { + let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } + self.controllerInteraction.displayUndo(.sticker(context: context, file: firstLockedPremiumEmoji, title: nil, text: presentationData.strings.EmojiInput_PremiumEmojiToast_Text, undoText: presentationData.strings.EmojiInput_PremiumEmojiToast_Action, customAction: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.dismissTextInput() + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + strongSelf.controller?.present(controller, in: .window(.root), with: nil) + })) + + return + } + let timestamp = CACurrentMediaTime() if self.lastSendTimestamp + 0.15 > timestamp { return @@ -2428,20 +2930,17 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.updateTypingActivity(false) - var messages: [EnqueueMessage] = [] - - let effectiveInputText = effectivePresentationInterfaceState.interfaceState.composeInputState.inputText let trimmedInputText = effectiveInputText.string.trimmingCharacters(in: .whitespacesAndNewlines) let peerId = effectivePresentationInterfaceState.chatLocation.peerId if peerId?.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = self.interactiveEmojis, interactiveEmojis.emojis.contains(trimmedInputText) { - messages.append(.message(text: "", attributes: [], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) + messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) } else { let inputText = convertMarkdownToAttributes(effectiveInputText) for text in breakChatInputText(trimChatInputText(inputText)) { if text.length != 0 { var attributes: [MessageAttribute] = [] - let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: 0/*Int(self.context.userLimits.maxAnimatedEmojisInText)*/)) + let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: 0)) if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } @@ -2452,17 +2951,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { webpage = self.chatPresentationInterfaceState.urlPreview?.1 } - messages.append(.message(text: text.string, attributes: attributes, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) - - #if DEBUG - if text.string == "sleep" { - messages.removeAll() - - for i in 0 ..< 5 { - messages.append(.message(text: "sleep\(i)", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) - } - } - #endif + messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) } } @@ -2509,6 +2998,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.setupSendActionOnViewUpdate({ [weak self] in if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode { + strongSelf.collapseInput() + strongSelf.ignoreUpdateHeight = true textInputPanelNode.text = "" strongSelf.requestUpdateChatInterfaceState(.immediate, true, { $0.withUpdatedReplyMessageId(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeDisableUrlPreview(nil) }) @@ -2548,7 +3039,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } func updatePlainInputSeparator(transition: ContainedViewLayoutTransition) { - let resolvedValue: CGFloat + var resolvedValue: CGFloat if self.accessoryPanelNode != nil { resolvedValue = 1.0 } else if self.usePlainInputSeparator { @@ -2557,6 +3048,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { resolvedValue = 1.0 } + resolvedValue = resolvedValue * (1.0 - self.inputPanelContainerNode.expansionFraction) + if resolvedValue != self.inputPanelBackgroundSeparatorNode.alpha { transition.updateAlpha(node: self.inputPanelBackgroundSeparatorNode, alpha: resolvedValue, beginWithCurrentState: true) } diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index 5b87ffd1fe..bf7c3fe2f8 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -134,7 +134,7 @@ final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNodeSticke guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self, self.stickerNode.bounds) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil) } func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { @@ -303,7 +303,7 @@ final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeStickerC guard let stickerItem = self.stickerItem else { return } - let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self, self.stickerNode.bounds) + let _ = self.interaction?.sendSticker(.standalone(media: stickerItem.stickerItem.file), false, self.view, self.stickerNode.bounds, nil) } func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize { diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift new file mode 100644 index 0000000000..9f068eee88 --- /dev/null +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -0,0 +1,2143 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import AccountContext +import ChatPresentationInterfaceState +import ComponentFlow +import EntityKeyboard +import AnimationCache +import MultiAnimationRenderer +import Postbox +import TelegramCore +import ComponentDisplayAdapters +import SettingsUI +import TextFormat +import PagerComponent +import AppBundle +import PremiumUI +import AudioToolbox +import UndoUI +import ContextUI +import GalleryUI +import AttachmentTextInputPanelNode +import TelegramPresentationData +import TelegramNotices + +private let staticEmojiMapping: [(EmojiPagerContentComponent.StaticEmojiSegment, [String])] = { + guard let path = getAppBundle().path(forResource: "emoji1016", ofType: "txt") else { + return [] + } + guard let string = try? String(contentsOf: URL(fileURLWithPath: path)) else { + return [] + } + + var result: [(EmojiPagerContentComponent.StaticEmojiSegment, [String])] = [] + + let orderedSegments = EmojiPagerContentComponent.StaticEmojiSegment.allCases + + let segments = string.components(separatedBy: "\n\n") + for i in 0 ..< min(segments.count, orderedSegments.count) { + let list = segments[i].components(separatedBy: " ") + result.append((orderedSegments[i], list)) + } + + return result +}() + +final class EntityKeyboardGifContent: Equatable { + let hasRecentGifs: Bool + let component: GifPagerContentComponent + + init(hasRecentGifs: Bool, component: GifPagerContentComponent) { + self.hasRecentGifs = hasRecentGifs + self.component = component + } + + static func ==(lhs: EntityKeyboardGifContent, rhs: EntityKeyboardGifContent) -> Bool { + if lhs.hasRecentGifs != rhs.hasRecentGifs { + return false + } + if lhs.component != rhs.component { + return false + } + return true + } +} + +final class ChatEntityKeyboardInputNode: ChatInputNode { + struct InputData: Equatable { + var emoji: EmojiPagerContentComponent + var stickers: EmojiPagerContentComponent? + var gifs: EntityKeyboardGifContent? + var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] + + init( + emoji: EmojiPagerContentComponent, + stickers: EmojiPagerContentComponent?, + gifs: EntityKeyboardGifContent?, + availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] + ) { + self.emoji = emoji + self.stickers = stickers + self.gifs = gifs + self.availableGifSearchEmojies = availableGifSearchEmojies + } + } + + static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, isStandalone: Bool, isSecret: Bool) -> Signal { + let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged + + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let isPremiumDisabled = premiumConfiguration.isPremiumDisabled + + let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings + + let emojiItems: Signal = combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.LocalRecentEmoji], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + hasPremium, + context.account.viewTracker.featuredEmojiPacks() + ) + |> map { view, hasPremium, featuredEmojiPacks -> EmojiPagerContentComponent in + struct ItemGroup { + var supergroupId: AnyHashable + var id: AnyHashable + var title: String + var subtitle: String? + var isPremiumLocked: Bool + var isFeatured: Bool + var isExpandable: Bool + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] + + var recentEmoji: OrderedItemListView? + for orderedView in view.orderedItemListsViews { + if orderedView.collectionId == Namespaces.OrderedItemList.LocalRecentEmoji { + recentEmoji = orderedView + } + } + + if let recentEmoji = recentEmoji { + for item in recentEmoji.items { + guard let item = item.contents.get(RecentEmojiItem.self) else { + continue + } + + if case let .file(file) = item.content, isPremiumDisabled, file.isPremiumEmoji { + continue + } + + if isSecret, case .file = item.content { + continue + } + + let resultItem: EmojiPagerContentComponent.Item + switch item.content { + case let .file(file): + resultItem = EmojiPagerContentComponent.Item( + file: file, + staticEmoji: nil, + subgroupId: nil + ) + case let .text(text): + resultItem = EmojiPagerContentComponent.Item( + file: nil, + staticEmoji: text, + subgroupId: nil + ) + } + + let groupId = "recent" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Stickers_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) + } + } + } + + for (subgroupId, list) in staticEmojiMapping { + let groupId: AnyHashable = "static" + for emojiString in list { + let resultItem = EmojiPagerContentComponent.Item( + file: nil, + staticEmoji: emojiString, + subgroupId: subgroupId.rawValue + ) + + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) + } + } + } + + var installedCollectionIds = Set() + for (id, _, _) in view.collectionInfos { + installedCollectionIds.insert(id) + } + + if !isSecret { + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let supergroupId = entry.index.collectionId + let groupId: AnyHashable = supergroupId + let isPremiumLocked: Bool = item.file.isPremiumEmoji && !hasPremium + if isPremiumLocked && isPremiumDisabled { + continue + } + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + + var title = "" + inner: for (id, info, _) in view.collectionInfos { + if id == entry.index.collectionId, let info = info as? StickerPackCollectionInfo { + title = info.title + break inner + } + } + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, isExpandable: false, items: [resultItem])) + } + } + + if !isStandalone { + for featuredEmojiPack in featuredEmojiPacks { + if installedCollectionIds.contains(featuredEmojiPack.info.id) { + continue + } + + for item in featuredEmojiPack.topItems { + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let supergroupId = featuredEmojiPack.info.id + let groupId: AnyHashable = supergroupId + let isPremiumLocked: Bool = item.file.isPremiumEmoji && !hasPremium + if isPremiumLocked && isPremiumDisabled { + continue + } + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, isExpandable: true, items: [resultItem])) + } + } + } + } + } + + return EmojiPagerContentComponent( + id: "emoji", + context: context, + animationCache: animationCache, + animationRenderer: animationRenderer, + inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(), + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var hasClear = false + if group.id == AnyHashable("recent") { + hasClear = true + } + + return EmojiPagerContentComponent.ItemGroup( + supergroupId: group.supergroupId, + groupId: group.id, + title: group.title, + subtitle: group.subtitle, + actionButtonTitle: nil, + isFeatured: group.isFeatured, + isPremiumLocked: group.isPremiumLocked, + isEmbedded: false, + hasClear: hasClear, + isExpandable: group.isExpandable, + displayPremiumBadges: false, + items: group.items + ) + }, + itemLayoutType: .compact + ) + } + return emojiItems + } + + static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction?, chatPeerId: PeerId?) -> Signal { + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let isPremiumDisabled = premiumConfiguration.isPremiumDisabled + + let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged + + let animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + let animationRenderer: MultiAnimationRenderer + /*if #available(iOS 13.0, *) { + animationRenderer = MultiAnimationMetalRendererImpl() + } else {*/ + animationRenderer = MultiAnimationRendererImpl() + //} + + let emojiItems = emojiInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, isStandalone: false, isSecret: chatPeerId?.namespace == Namespaces.Peer.SecretChat) + + let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] + let stickerOrderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] + + let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings + + let stickerItems: Signal = combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: stickerOrderedItemListCollectionIds, namespaces: stickerNamespaces, aroundIndex: nil, count: 10000000), + hasPremium, + context.account.viewTracker.featuredStickerPacks(), + context.engine.data.get(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: Namespaces.CachedItemCollection.featuredStickersConfiguration, id: ValueBoxKey(length: 0))), + ApplicationSpecificNotice.dismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager) + ) + |> map { view, hasPremium, featuredStickerPacks, featuredStickersConfiguration, dismissedTrendingStickerPacks -> EmojiPagerContentComponent in + struct ItemGroup { + var supergroupId: AnyHashable + var id: AnyHashable + var title: String + var subtitle: String? + var actionButtonTitle: String? + var isPremiumLocked: Bool + var isFeatured: Bool + var displayPremiumBadges: Bool + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] + + var savedStickers: OrderedItemListView? + var recentStickers: OrderedItemListView? + var premiumStickers: OrderedItemListView? + var cloudPremiumStickers: OrderedItemListView? + for orderedView in view.orderedItemListsViews { + if orderedView.collectionId == Namespaces.OrderedItemList.CloudRecentStickers { + recentStickers = orderedView + } else if orderedView.collectionId == Namespaces.OrderedItemList.CloudSavedStickers { + savedStickers = orderedView + } else if orderedView.collectionId == Namespaces.OrderedItemList.PremiumStickers { + premiumStickers = orderedView + } else if orderedView.collectionId == Namespaces.OrderedItemList.CloudPremiumStickers { + cloudPremiumStickers = orderedView + } + } + + var installedCollectionIds = Set() + for (id, _, _) in view.collectionInfos { + installedCollectionIds.insert(id) + } + + let dismissedTrendingStickerPacksSet = Set(dismissedTrendingStickerPacks ?? []) + let featuredStickerPacksSet = Set(featuredStickerPacks.map(\.info.id.id)) + + if dismissedTrendingStickerPacksSet != featuredStickerPacksSet { + let featuredStickersConfiguration = featuredStickersConfiguration?.get(FeaturedStickersConfiguration.self) + for featuredStickerPack in featuredStickerPacks { + if installedCollectionIds.contains(featuredStickerPack.info.id) { + continue + } + + guard let item = featuredStickerPack.topItems.first else { + continue + } + + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let supergroupId = "featuredTop" + let groupId: AnyHashable = supergroupId + let isPremiumLocked: Bool = item.file.isPremiumSticker && !hasPremium + if isPremiumLocked && isPremiumDisabled { + continue + } + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + + let trendingIsPremium = featuredStickersConfiguration?.isPremium ?? false + let title = trendingIsPremium ? strings.Stickers_TrendingPremiumStickers : strings.StickerPacksSettings_FeaturedPacks + + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + } + } + } + + if let savedStickers = savedStickers { + for item in savedStickers.items { + guard let item = item.contents.get(SavedStickerItem.self) else { + continue + } + if isPremiumDisabled && item.file.isPremiumSticker { + continue + } + + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let groupId = "saved" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleFavoriteStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + } + } + } + + if let recentStickers = recentStickers { + for item in recentStickers.items { + guard let item = item.contents.get(RecentMediaItem.self) else { + continue + } + if isPremiumDisabled && item.media.isPremiumSticker { + continue + } + + let resultItem = EmojiPagerContentComponent.Item( + file: item.media, + staticEmoji: nil, + subgroupId: nil + ) + + let groupId = "recent" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Stickers_FrequentlyUsed, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + } + } + } + + var hasPremiumStickers = false + if hasPremium { + if let premiumStickers = premiumStickers, !premiumStickers.items.isEmpty { + hasPremiumStickers = true + } else if let cloudPremiumStickers = cloudPremiumStickers, !cloudPremiumStickers.items.isEmpty { + hasPremiumStickers = true + } + } + + if hasPremiumStickers { + var premiumStickers = premiumStickers?.items ?? [] + if let cloudPremiumStickers = cloudPremiumStickers { + premiumStickers.append(contentsOf: cloudPremiumStickers.items) + } + + var processedIds = Set() + for item in premiumStickers { + guard let item = item.contents.get(RecentMediaItem.self) else { + continue + } + if isPremiumDisabled && item.media.isPremiumSticker { + continue + } + if processedIds.contains(item.media.fileId) { + continue + } + processedIds.insert(item.media.fileId) + + let resultItem = EmojiPagerContentComponent.Item( + file: item.media, + staticEmoji: nil, + subgroupId: nil + ) + + let groupId = "premium" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitlePremiumStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + } + } + } + + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + let groupId = entry.index.collectionId + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + + var title = "" + inner: for (id, info, _) in view.collectionInfos { + if id == groupId, let info = info as? StickerPackCollectionInfo { + title = info.title + break inner + } + } + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: true, items: [resultItem])) + } + } + + for featuredStickerPack in featuredStickerPacks { + if installedCollectionIds.contains(featuredStickerPack.info.id) { + continue + } + + for item in featuredStickerPack.topItems { + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let supergroupId = featuredStickerPack.info.id + let groupId: AnyHashable = supergroupId + let isPremiumLocked: Bool = item.file.isPremiumSticker && !hasPremium + if isPremiumLocked && isPremiumDisabled { + continue + } + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + + let subtitle: String = strings.StickerPack_StickerCount(Int32(featuredStickerPack.info.count)) + + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: featuredStickerPack.info.title, subtitle: subtitle, actionButtonTitle: strings.Stickers_Install, isPremiumLocked: isPremiumLocked, isFeatured: true, displayPremiumBadges: false, items: [resultItem])) + } + } + } + + return EmojiPagerContentComponent( + id: "stickers", + context: context, + animationCache: animationCache, + animationRenderer: animationRenderer, + inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(), + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var hasClear = false + var isEmbedded = false + if group.id == AnyHashable("recent") { + hasClear = true + } else if group.id == AnyHashable("featuredTop") { + hasClear = true + isEmbedded = true + } + + return EmojiPagerContentComponent.ItemGroup( + supergroupId: group.supergroupId, + groupId: group.id, + title: group.title, + subtitle: group.subtitle, + actionButtonTitle: group.actionButtonTitle, + isFeatured: group.isFeatured, + isPremiumLocked: group.isPremiumLocked, + isEmbedded: isEmbedded, + hasClear: hasClear, + isExpandable: false, + displayPremiumBadges: group.displayPremiumBadges, + items: group.items + ) + }, + itemLayoutType: .detailed + ) + } + + let reactions: Signal<[String], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()) + |> map { appConfiguration -> [String] in + let defaultReactions: [String] = ["👍", "👎", "😍", "😂", "😯", "😕", "😢", "😡", "💪", "👏", "🙈", "😒"] + + guard let data = appConfiguration.data, let emojis = data["gif_search_emojies"] as? [String] else { + return defaultReactions + } + return emojis + } + |> distinctUntilChanged + + let animatedEmojiStickers = context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false) + |> map { animatedEmoji -> [String: [StickerPackItem]] in + var animatedEmojiStickers: [String: [StickerPackItem]] = [:] + switch animatedEmoji { + case let .result(_, items, _): + for item in items { + if let emoji = item.getStringRepresentationsOfIndexKeys().first { + animatedEmojiStickers[emoji.basicEmoji.0] = [item] + let strippedEmoji = emoji.basicEmoji.0.strippedEmoji + if animatedEmojiStickers[strippedEmoji] == nil { + animatedEmojiStickers[strippedEmoji] = [item] + } + } + } + default: + break + } + return animatedEmojiStickers + } + + let gifInputInteraction = GifPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction] item, view, rect in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendGif(item.file, view, rect, false, false) + }, + openGifContextMenu: { _, _, _, _, _ in + }, + loadMore: { _ in + } + ) + + // We are going to subscribe to the actual data when the view is loaded + let gifItems: Signal = .single(EntityKeyboardGifContent( + hasRecentGifs: true, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: .recent, + items: [], + isLoading: false, + loadMoreToken: nil + ) + )) + + return combineLatest(queue: .mainQueue(), + emojiItems, + stickerItems, + gifItems, + reactions, + animatedEmojiStickers + ) + |> map { emoji, stickers, gifs, reactions, animatedEmojiStickers -> InputData in + var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] = [] + for reaction in reactions { + if let file = animatedEmojiStickers[reaction]?.first?.file { + var title: String? + switch reaction { + case "😡": + title = strings.Gif_Emotion_Angry + case "😮": + title = strings.Gif_Emotion_Surprised + case "😂": + title = strings.Gif_Emotion_Joy + case "😘": + title = strings.Gif_Emotion_Kiss + case "😍": + title = strings.Gif_Emotion_Hearts + case "👍": + title = strings.Gif_Emotion_ThumbsUp + case "👎": + title = strings.Gif_Emotion_ThumbsDown + case "🙄": + title = strings.Gif_Emotion_RollEyes + case "😎": + title = strings.Gif_Emotion_Cool + case "🥳": + title = strings.Gif_Emotion_Party + default: + break + } + + guard let title = title else { + continue + } + + availableGifSearchEmojies.append(EntityKeyboardComponent.GifSearchEmoji(emoji: reaction, file: file, title: title)) + } + } + + return InputData( + emoji: emoji, + stickers: stickers, + gifs: gifs, + availableGifSearchEmojies: availableGifSearchEmojies + ) + } + } + + private let context: AccountContext + private let entityKeyboardView: ComponentHostView + + private let defaultToEmojiTab: Bool + private var currentInputData: InputData + private var inputDataDisposable: Disposable? + private var hasRecentGifsDisposable: Disposable? + + private let controllerInteraction: ChatControllerInteraction? + + private var inputNodeInteraction: ChatMediaInputNodeInteraction? + + private let trendingGifsPromise = Promise(nil) + + private var isMarkInputCollapsed: Bool = false + + var externalTopPanelContainerImpl: PagerExternalTopPanelContainer? + override var externalTopPanelContainer: UIView? { + return self.externalTopPanelContainerImpl + } + + var switchToTextInput: (() -> Void)? + + private var currentState: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool)? + + private var scheduledContentAnimationHint: EmojiPagerContentComponent.ContentAnimation? + private var scheduledInnerTransition: Transition? + + private var gifMode: GifPagerContentComponent.Subject? { + didSet { + if let gifMode = self.gifMode, gifMode != oldValue { + self.reloadGifContext() + } + } + } + + var canSwitchToTextInputAutomatically: Bool { + if let pagerView = self.entityKeyboardView.componentView as? EntityKeyboardComponent.View, let centralId = pagerView.centralId { + if centralId == AnyHashable("emoji") { + return false + } + } + return true + } + + private final class GifContext { + private var componentValue: EntityKeyboardGifContent? { + didSet { + if let componentValue = self.componentValue { + self.componentResult.set(.single(componentValue)) + } + } + } + private let componentPromise = Promise() + + private let componentResult = Promise() + var component: Signal { + return self.componentResult.get() + } + private var componentDisposable: Disposable? + + private let context: AccountContext + private let subject: GifPagerContentComponent.Subject + private let gifInputInteraction: GifPagerContentComponent.InputInteraction + + private var loadingMoreToken: String? + + init(context: AccountContext, subject: GifPagerContentComponent.Subject, gifInputInteraction: GifPagerContentComponent.InputInteraction, trendingGifs: Signal) { + self.context = context + self.subject = subject + self.gifInputInteraction = gifInputInteraction + + let hasRecentGifs = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> Bool in + return !savedGifs.isEmpty + } + + let gifItems: Signal + switch subject { + case .recent: + gifItems = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> EntityKeyboardGifContent in + var items: [GifPagerContentComponent.Item] = [] + for gifItem in savedGifs { + items.append(GifPagerContentComponent.Item( + file: .savedGif(media: gifItem.contents.get(RecentMediaItem.self)!.media), + contextResult: nil + )) + } + return EntityKeyboardGifContent( + hasRecentGifs: true, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: false, + loadMoreToken: nil + ) + ) + } + case .trending: + gifItems = combineLatest(hasRecentGifs, trendingGifs) + |> map { hasRecentGifs, trendingGifs -> EntityKeyboardGifContent in + var items: [GifPagerContentComponent.Item] = [] + + var isLoading = false + if let trendingGifs = trendingGifs { + for file in trendingGifs.files { + items.append(GifPagerContentComponent.Item( + file: file.file, + contextResult: file.contextResult + )) + } + } else { + isLoading = true + } + + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: nil + ) + ) + } + case let .emojiSearch(query): + gifItems = combineLatest(hasRecentGifs, paneGifSearchForQuery(context: context, query: query, offset: nil, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil)) + |> map { hasRecentGifs, result -> EntityKeyboardGifContent in + var items: [GifPagerContentComponent.Item] = [] + + var loadMoreToken: String? + var isLoading = false + if let result = result { + for file in result.files { + items.append(GifPagerContentComponent.Item( + file: file.file, + contextResult: file.contextResult + )) + } + loadMoreToken = result.nextOffset + } else { + isLoading = true + } + + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: loadMoreToken + ) + ) + } + } + + self.componentPromise.set(gifItems) + self.componentDisposable = (self.componentPromise.get() + |> deliverOnMainQueue).start(next: { [weak self] result in + guard let strongSelf = self else { + return + } + strongSelf.componentValue = result + }) + } + + deinit { + self.componentDisposable?.dispose() + } + + func loadMore(token: String) { + if self.loadingMoreToken == token { + return + } + self.loadingMoreToken = token + + guard let componentValue = self.componentValue else { + return + } + + let context = self.context + let subject = self.subject + let gifInputInteraction = self.gifInputInteraction + + switch self.subject { + case let .emojiSearch(query): + let hasRecentGifs = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> Bool in + return !savedGifs.isEmpty + } + + let gifItems: Signal + gifItems = combineLatest(hasRecentGifs, paneGifSearchForQuery(context: context, query: query, offset: token, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil)) + |> map { hasRecentGifs, result -> EntityKeyboardGifContent in + var items: [GifPagerContentComponent.Item] = [] + var existingIds = Set() + for item in componentValue.component.items { + items.append(item) + existingIds.insert(item.file.media.fileId) + } + + var loadMoreToken: String? + var isLoading = false + if let result = result { + for file in result.files { + if existingIds.contains(file.file.media.fileId) { + continue + } + existingIds.insert(file.file.media.fileId) + items.append(GifPagerContentComponent.Item( + file: file.file, + contextResult: file.contextResult + )) + } + if !result.isComplete { + loadMoreToken = result.nextOffset + } + } else { + isLoading = true + } + + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: loadMoreToken + ) + ) + } + + self.componentPromise.set(gifItems) + default: + break + } + } + } + private var gifContext: GifContext? { + didSet { + if let gifContext = self.gifContext { + self.gifComponent.set(gifContext.component) + } + } + } + private let gifComponent = Promise() + private var gifInputInteraction: GifPagerContentComponent.InputInteraction? + + fileprivate var emojiInputInteraction: EmojiPagerContentComponent.InputInteraction? + private var stickerInputInteraction: EmojiPagerContentComponent.InputInteraction? + + private weak var currentUndoOverlayController: UndoOverlayController? + + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPeerId: PeerId?) { + self.context = context + self.currentInputData = currentInputData + self.defaultToEmojiTab = defaultToEmojiTab + + self.controllerInteraction = controllerInteraction + + self.entityKeyboardView = ComponentHostView() + + super.init() + + self.topBackgroundExtension = 34.0 + self.followsDefaultHeight = true + + self.view.addSubview(self.entityKeyboardView) + + self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer() + + let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged + + self.emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak self, weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard let strongSelf = self, let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { + return + } + + if let file = item.file { + var text = "." + var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? + loop: for attribute in file.attributes { + switch attribute { + case let .CustomEmoji(_, displayText, packReference): + text = displayText + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + break loop + default: + break + } + } + + if file.isPremiumEmoji && !hasPremium { + var animateInAsReplacement = false + if let currentUndoOverlayController = strongSelf.currentUndoOverlayController { + currentUndoOverlayController.dismissWithCommitActionAndReplacementAnimation() + strongSelf.currentUndoOverlayController = nil + animateInAsReplacement = true + } + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: presentationData.strings.EmojiInput_PremiumEmojiToast_Text, undoText: presentationData.strings.EmojiInput_PremiumEmojiToast_Action, customAction: { [weak controllerInteraction] in + guard let controllerInteraction = controllerInteraction else { + return + } + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + controllerInteraction.navigationController()?.pushViewController(controller) + + /*let controller = PremiumIntroScreen(context: context, source: .stickers) + controllerInteraction.navigationController()?.pushViewController(controller)*/ + }), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return false }) + strongSelf.currentUndoOverlayController = controller + controllerInteraction.presentController(controller, nil) + return + } + + if let emojiAttribute = emojiAttribute { + AudioServicesPlaySystemSound(0x450) + interfaceInteraction.insertText(NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: emojiAttribute])) + } + } else if let staticEmoji = item.staticEmoji { + AudioServicesPlaySystemSound(0x450) + interfaceInteraction.insertText(NSAttributedString(string: staticEmoji, attributes: [:])) + } + }) + }, + deleteBackwards: { [weak interfaceInteraction] in + guard let interfaceInteraction = interfaceInteraction else { + return + } + interfaceInteraction.backwardsDeleteText() + }, + openStickerSettings: { + }, + openFeatured: { + }, + addGroupAction: { [weak self, weak controllerInteraction] groupId, isPremiumLocked in + guard let controllerInteraction = controllerInteraction, let collectionId = groupId.base as? ItemCollectionId else { + return + } + + if isPremiumLocked { + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + controllerInteraction.navigationController()?.pushViewController(controller) + + return + } + + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) + let _ = (context.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { views in + guard let view = views.views[viewKey] as? OrderedItemListView else { + return + } + for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + if featuredEmojiPack.info.id == collectionId { + if let strongSelf = self { + strongSelf.scheduledContentAnimationHint = EmojiPagerContentComponent.ContentAnimation(type: .groupInstalled(id: collectionId)) + } + let _ = context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start() + + break + } + } + }) + }, + clearGroup: { [weak controllerInteraction] groupId in + guard let controllerInteraction = controllerInteraction else { + return + } + if groupId == AnyHashable("recent") { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) + var items: [ActionSheetItem] = [] + items.append(ActionSheetButtonItem(title: presentationData.strings.Emoji_ClearRecent, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + let _ = context.engine.stickers.clearRecentlyUsedEmoji().start() + })) + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + controllerInteraction.presentController(actionSheet, nil) + } + }, + pushController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.navigationController()?.pushViewController(controller) + }, + presentController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.presentController(controller, nil) + }, + presentGlobalOverlayController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.presentGlobalOverlayController(controller, nil) + }, + navigationController: { [weak controllerInteraction] in + return controllerInteraction?.navigationController() + }, + sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer) + }, + chatPeerId: chatPeerId + ) + + self.stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction, weak interfaceInteraction] groupId, item, view, rect, layer in + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { + return + } + guard let file = item.file else { + return + } + + if groupId == AnyHashable("featuredTop") { + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) + let _ = (context.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak controllerInteraction] views in + guard let controllerInteraction = controllerInteraction else { + return + } + guard let view = views.views[viewKey] as? OrderedItemListView else { + return + } + for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + if featuredStickerPack.topItems.contains(where: { $0.file.fileId == file.fileId }) { + controllerInteraction.navigationController()?.pushViewController(FeaturedStickersScreen( + context: context, + highlightedPackId: featuredStickerPack.info.id, + sendSticker: { [weak controllerInteraction] fileReference, sourceNode, sourceRect in + guard let controllerInteraction = controllerInteraction else { + return false + } + return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + } + )) + + break + } + } + }) + } else { + if file.isPremiumSticker && !hasPremium { + let controller = PremiumIntroScreen(context: context, source: .stickers) + controllerInteraction.navigationController()?.pushViewController(controller) + + return + } + let _ = interfaceInteraction.sendSticker(.standalone(media: file), false, view, rect, layer) + } + }) + }, + deleteBackwards: { [weak interfaceInteraction] in + guard let interfaceInteraction = interfaceInteraction else { + return + } + interfaceInteraction.backwardsDeleteText() + }, + openStickerSettings: { [weak controllerInteraction] in + guard let controllerInteraction = controllerInteraction else { + return + } + let controller = installedStickerPacksController(context: context, mode: .modal) + controller.navigationPresentation = .modal + controllerInteraction.navigationController()?.pushViewController(controller) + }, + openFeatured: { [weak controllerInteraction] in + guard let controllerInteraction = controllerInteraction else { + return + } + + controllerInteraction.navigationController()?.pushViewController(FeaturedStickersScreen( + context: context, + highlightedPackId: nil, + sendSticker: { [weak controllerInteraction] fileReference, sourceNode, sourceRect in + guard let controllerInteraction = controllerInteraction else { + return false + } + return controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) + } + )) + }, + addGroupAction: { groupId, isPremiumLocked in + guard let controllerInteraction = controllerInteraction, let collectionId = groupId.base as? ItemCollectionId else { + return + } + + if isPremiumLocked { + let controller = PremiumIntroScreen(context: context, source: .stickers) + controllerInteraction.navigationController()?.pushViewController(controller) + + return + } + + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) + let _ = (context.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { views in + guard let view = views.views[viewKey] as? OrderedItemListView else { + return + } + for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + if featuredStickerPack.info.id == collectionId { + let _ = (context.engine.stickers.loadedStickerPack(reference: .id(id: featuredStickerPack.info.id.id, accessHash: featuredStickerPack.info.accessHash), forceActualized: false) + |> mapToSignal { result -> Signal in + switch result { + case let .result(info, items, installed): + if installed { + return .complete() + } else { + return context.engine.stickers.addStickerPackInteractively(info: info, items: items) + } + case .fetching: + break + case .none: + break + } + return .complete() + } + |> deliverOnMainQueue).start(completed: { + }) + + break + } + } + }) + }, + clearGroup: { [weak controllerInteraction] groupId in + guard let controllerInteraction = controllerInteraction else { + return + } + if groupId == AnyHashable("recent") { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let actionSheet = ActionSheetController(theme: ActionSheetControllerTheme(presentationTheme: presentationData.theme, fontSize: presentationData.listsFontSize)) + var items: [ActionSheetItem] = [] + items.append(ActionSheetButtonItem(title: presentationData.strings.Stickers_ClearRecent, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + let _ = context.engine.stickers.clearRecentlyUsedStickers().start() + })) + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + controllerInteraction.presentController(actionSheet, nil) + } else if groupId == AnyHashable("featuredTop") { + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedStickerPacks) + let _ = (context.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { views in + guard let view = views.views[viewKey] as? OrderedItemListView else { + return + } + var stickerPackIds: [Int64] = [] + for featuredStickerPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + stickerPackIds.append(featuredStickerPack.info.id.id) + } + let _ = ApplicationSpecificNotice.setDismissedTrendingStickerPacks(accountManager: context.sharedContext.accountManager, values: stickerPackIds).start() + }) + } + }, + pushController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.navigationController()?.pushViewController(controller) + }, + presentController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.presentController(controller, nil) + }, + presentGlobalOverlayController: { [weak controllerInteraction] controller in + guard let controllerInteraction = controllerInteraction else { + return + } + controllerInteraction.presentGlobalOverlayController(controller, nil) + }, + navigationController: { [weak controllerInteraction] in + return controllerInteraction?.navigationController() + }, + sendSticker: { [weak controllerInteraction] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendSticker(fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer) + }, + chatPeerId: chatPeerId + ) + + self.inputDataDisposable = (combineLatest(queue: .mainQueue(), + updatedInputData, + self.gifComponent.get() + ) + |> deliverOnMainQueue).start(next: { [weak self] inputData, gifs in + guard let strongSelf = self else { + return + } + var inputData = inputData + inputData.gifs = gifs + + var transition: Transition = .immediate + var useAnimation = false + + if let pagerView = strongSelf.entityKeyboardView.componentView as? EntityKeyboardComponent.View, let centralId = pagerView.centralId { + if centralId == AnyHashable("emoji") { + useAnimation = strongSelf.currentInputData.emoji != inputData.emoji + } else if centralId == AnyHashable("stickers"), strongSelf.currentInputData.stickers != nil, inputData.stickers != nil { + useAnimation = strongSelf.currentInputData.stickers != inputData.stickers + } + } + + if useAnimation { + let contentAnimation: EmojiPagerContentComponent.ContentAnimation + if let scheduledContentAnimationHint = strongSelf.scheduledContentAnimationHint { + strongSelf.scheduledContentAnimationHint = nil + contentAnimation = scheduledContentAnimationHint + } else { + contentAnimation = EmojiPagerContentComponent.ContentAnimation(type: .generic) + } + transition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(contentAnimation) + } + strongSelf.currentInputData = inputData + strongSelf.performLayout(transition: transition) + }) + + self.inputNodeInteraction = ChatMediaInputNodeInteraction( + navigateToCollectionId: { _ in + }, + navigateBackToStickers: { + }, + setGifMode: { _ in + }, + openSettings: { + }, + openTrending: { _ in + }, + dismissTrendingPacks: { _ in + }, + toggleSearch: { _, _, _ in + }, + openPeerSpecificSettings: { + }, + dismissPeerSpecificSettings: { + }, + clearRecentlyUsedStickers: { + } + ) + + self.trendingGifsPromise.set(.single(nil)) + self.trendingGifsPromise.set(paneGifSearchForQuery(context: context, query: "", offset: nil, incompleteResults: true, delayRequest: false, updateActivity: nil) + |> map { items -> ChatMediaInputGifPaneTrendingState? in + if let items = items { + return ChatMediaInputGifPaneTrendingState(files: items.files, nextOffset: items.nextOffset) + } else { + return nil + } + }) + + self.gifInputInteraction = GifPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction] item, view, rect in + guard let controllerInteraction = controllerInteraction else { + return + } + + if let (collection, result) = item.contextResult { + let _ = controllerInteraction.sendBotContextResultAsGif(collection, result, view, rect, false) + } else { + let _ = controllerInteraction.sendGif(item.file, view, rect, false, false) + } + }, + openGifContextMenu: { [weak self] item, sourceView, sourceRect, gesture, isSaved in + guard let strongSelf = self else { + return + } + strongSelf.openGifContextMenu(item: item, sourceView: sourceView, sourceRect: sourceRect, gesture: gesture, isSaved: isSaved) + }, + loadMore: { [weak self] token in + guard let strongSelf = self, let gifContext = strongSelf.gifContext else { + return + } + gifContext.loadMore(token: token) + } + ) + + self.switchToTextInput = { [weak self] in + guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else { + return + } + controllerInteraction.updateInputMode { _ in + return .text + } + } + + let hasRecentGifs = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> Bool in + return !savedGifs.isEmpty + } + + self.hasRecentGifsDisposable = (hasRecentGifs + |> deliverOnMainQueue).start(next: { [weak self] hasRecentGifs in + guard let strongSelf = self else { + return + } + + if let gifMode = strongSelf.gifMode { + if !hasRecentGifs, case .recent = gifMode { + strongSelf.gifMode = .trending + } + } else { + strongSelf.gifMode = hasRecentGifs ? .recent : .trending + } + }) + } + + deinit { + self.inputDataDisposable?.dispose() + self.hasRecentGifsDisposable?.dispose() + } + + private func reloadGifContext() { + if let gifInputInteraction = self.gifInputInteraction, let gifMode = self.gifMode { + self.gifContext = GifContext(context: self.context, subject: gifMode, gifInputInteraction: gifInputInteraction, trendingGifs: self.trendingGifsPromise.get()) + } + } + + func markInputCollapsed() { + self.isMarkInputCollapsed = true + } + + private func performLayout(transition: Transition) { + guard let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.currentState else { + return + } + self.scheduledInnerTransition = transition + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) + } + + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) { + self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) + + let innerTransition: Transition + if let scheduledInnerTransition = self.scheduledInnerTransition { + self.scheduledInnerTransition = nil + innerTransition = scheduledInnerTransition + } else { + innerTransition = Transition(transition) + } + + let wasMarkedInputCollapsed = self.isMarkInputCollapsed + self.isMarkInputCollapsed = false + + let expandedHeight = standardInputHeight + + var hiddenInputHeight: CGFloat = 0.0 + if self.hideInput && !self.adjustLayoutForHiddenInput { + hiddenInputHeight = inputPanelHeight + } + + let context = self.context + let controllerInteraction = self.controllerInteraction + let inputNodeInteraction = self.inputNodeInteraction! + let trendingGifsPromise = self.trendingGifsPromise + + var mappedTransition = innerTransition + + if wasMarkedInputCollapsed || !isExpanded { + mappedTransition = mappedTransition.withUserData(EntityKeyboardComponent.MarkInputCollapsed()) + } + + var stickerContent: EmojiPagerContentComponent? = self.currentInputData.stickers + var gifContent: EntityKeyboardGifContent? = self.currentInputData.gifs + + var stickersEnabled = true + if let peer = interfaceState.renderedPeer?.peer as? TelegramChannel { + if peer.hasBannedPermission(.banSendStickers) != nil { + stickersEnabled = false + } + } else if let peer = interfaceState.renderedPeer?.peer as? TelegramGroup { + if peer.hasBannedPermission(.banSendStickers) { + stickersEnabled = false + } + } + + if !stickersEnabled || interfaceState.interfaceState.editMessage != nil { + stickerContent = nil + gifContent = nil + } + + stickerContent?.inputInteractionHolder.inputInteraction = self.stickerInputInteraction + self.currentInputData.emoji.inputInteractionHolder.inputInteraction = self.emojiInputInteraction + + let startTime = CFAbsoluteTimeGetCurrent() + + let entityKeyboardSize = self.entityKeyboardView.update( + transition: mappedTransition, + component: AnyComponent(EntityKeyboardComponent( + theme: interfaceState.theme, + strings: interfaceState.strings, + containerInsets: UIEdgeInsets(top: 0.0, left: leftInset, bottom: bottomInset, right: rightInset), + emojiContent: self.currentInputData.emoji, + stickerContent: stickerContent, + gifContent: gifContent?.component, + hasRecentGifs: gifContent?.hasRecentGifs ?? false, + availableGifSearchEmojies: self.currentInputData.availableGifSearchEmojies, + defaultToEmojiTab: self.defaultToEmojiTab, + externalTopPanelContainer: self.externalTopPanelContainerImpl, + topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in + guard let strongSelf = self else { + return + } + if strongSelf.topBackgroundExtension != topPanelExtension { + strongSelf.topBackgroundExtension = topPanelExtension + strongSelf.topBackgroundExtensionUpdated?(transition.containedViewLayoutTransition) + } + }, + hideInputUpdated: { [weak self] hideInput, adjustLayout, transition in + guard let strongSelf = self else { + return + } + if strongSelf.hideInput != hideInput || strongSelf.adjustLayoutForHiddenInput != adjustLayout { + strongSelf.hideInput = hideInput + strongSelf.adjustLayoutForHiddenInput = adjustLayout + strongSelf.hideInputUpdated?(transition.containedViewLayoutTransition) + } + }, + switchToTextInput: { [weak self] in + self?.switchToTextInput?() + }, + switchToGifSubject: { [weak self] subject in + guard let strongSelf = self else { + return + } + strongSelf.gifMode = subject + }, + makeSearchContainerNode: { [weak controllerInteraction] content in + guard let controllerInteraction = controllerInteraction else { + return nil + } + + let mappedMode: ChatMediaInputSearchMode + switch content { + case .stickers: + mappedMode = .sticker + case .gifs: + mappedMode = .gif + } + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + return PaneSearchContainerNode( + context: context, + theme: presentationData.theme, + strings: presentationData.strings, + controllerInteraction: controllerInteraction, + inputNodeInteraction: inputNodeInteraction, + mode: mappedMode, + trendingGifsPromise: trendingGifsPromise, + cancel: { + } + ) + }, + deviceMetrics: deviceMetrics, + hiddenInputHeight: hiddenInputHeight, + isExpanded: isExpanded + )), + environment: {}, + containerSize: CGSize(width: width, height: expandedHeight) + ) + transition.updateFrame(view: self.entityKeyboardView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: entityKeyboardSize)) + + let layoutTime = CFAbsoluteTimeGetCurrent() - startTime + if layoutTime > 0.1 { + #if DEBUG + print("EntityKeyboard layout in \(layoutTime * 1000.0) ms") + #endif + } + + return (expandedHeight, 0.0) + } + + private func openGifContextMenu(item: GifPagerContentComponent.Item, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + let file = item + + let canSaveGif: Bool + if file.file.media.fileId.namespace == Namespaces.Media.CloudFile { + canSaveGif = true + } else { + canSaveGif = false + } + + let _ = (self.context.engine.stickers.isGifSaved(id: file.file.media.fileId) + |> deliverOnMainQueue).start(next: { [weak self] isGifSaved in + guard let strongSelf = self else { + return + } + var isGifSaved = isGifSaved + if !canSaveGif { + isGifSaved = false + } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + + let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in + }, baseNavigationController: nil) + gallery.setHintWillBePresentedInPreviewingContext(true) + + var items: [ContextMenuItem] = [] + items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Send, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + if isSaved { + let _ = self?.controllerInteraction?.sendGif(file.file, sourceView, sourceRect, false, false) + } else if let (collection, result) = file.contextResult { + let _ = self?.controllerInteraction?.sendBotContextResultAsGif(collection, result, sourceView, sourceRect, false) + } + }))) + + if let currentState = strongSelf.currentState { + let interfaceState = currentState.interfaceState + + var isScheduledMessages = false + if case .scheduledMessages = interfaceState.subject { + isScheduledMessages = true + } + if !isScheduledMessages { + if case let .peer(peerId) = interfaceState.chatLocation { + if peerId != self?.context.account.peerId && peerId.namespace != Namespaces.Peer.SecretChat { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_SendSilently, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/SilentIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + if isSaved { + let _ = self?.controllerInteraction?.sendGif(file.file, sourceView, sourceRect, true, false) + } else if let (collection, result) = file.contextResult { + let _ = self?.controllerInteraction?.sendBotContextResultAsGif(collection, result, sourceView, sourceRect, true) + } + }))) + } + + if isSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + + let _ = self?.controllerInteraction?.sendGif(file.file, sourceView, sourceRect, false, true) + }))) + } + } + } + } + + if isSaved || isGifSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) + }, action: { _, f in + f(.dismissWithoutContent) + + guard let strongSelf = self else { + return + } + let _ = removeSavedGif(postbox: strongSelf.context.account.postbox, mediaId: file.file.media.fileId).start() + }))) + } else if canSaveGif && !isGifSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Preview_SaveGif, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.dismissWithoutContent) + + guard let strongSelf = self else { + return + } + + let context = strongSelf.context + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let _ = (toggleGifSaved(account: context.account, fileReference: file.file, saved: true) + |> deliverOnMainQueue).start(next: { result in + guard let strongSelf = self else { + return + } + switch result { + case .generic: + strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + case let .limitExceeded(limit, premiumLimit): + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let text: String + if limit == premiumLimit || premiumConfiguration.isPremiumDisabled { + text = presentationData.strings.Premium_MaxSavedGifsFinalText + } else { + text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string + } + strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in + guard let strongSelf = self else { + return false + } + + if case .info = action { + let controller = PremiumIntroScreen(context: context, source: .savedGifs) + strongSelf.controllerInteraction?.navigationController()?.pushViewController(controller) + return true + } + return false + }), nil) + } + }) + }))) + } + + let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceView: sourceView, sourceRect: sourceRect)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + strongSelf.controllerInteraction?.presentGlobalOverlayController(contextController, nil) + }) + + /*let canSaveGif: Bool + if item.file.fileId.namespace == Namespaces.Media.CloudFile { + canSaveGif = true + } else { + canSaveGif = false + } + + let _ = (self.context.engine.stickers.isGifSaved(id: file.fileId) + |> deliverOnMainQueue).start(next: { [weak self] isGifSaved in + guard let strongSelf = self else { + return + } + var isGifSaved = isGifSaved + if !canSaveGif { + isGifSaved = false + } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + + let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in + }, baseNavigationController: nil) + gallery.setHintWillBePresentedInPreviewingContext(true) + + var items: [ContextMenuItem] = [] + items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaPicker_Send, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + if isSaved { + let _ = self?.controllerInteraction?.sendGif(FileMediaReference.savedGif(media: file), sourceView, sourceRect, false, false) + }/* else if let (collection, result) = file.contextResult { + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, false) + }*/ + }))) + + if let currentState = strongSelf.currentState { + let interfaceState = currentState.interfaceState + + var isScheduledMessages = false + if case .scheduledMessages = interfaceState.subject { + isScheduledMessages = true + } + if !isScheduledMessages { + if case let .peer(peerId) = interfaceState.chatLocation { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + if peerId != self?.context.account.peerId && peerId.namespace != Namespaces.Peer.SecretChat { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_SendSilently, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/SilentIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + if isSaved { + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, true, false) + } else if let (collection, result) = file.contextResult { + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, true) + } + }))) + } + + if isSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.default) + + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, true) + }))) + } + } + } + } + + if isSaved || isGifSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor) + }, action: { _, f in + f(.dismissWithoutContent) + + guard let strongSelf = self else { + return + } + let _ = removeSavedGif(postbox: strongSelf.context.account.postbox, mediaId: file.fileId).start() + }))) + } else if canSaveGif && !isGifSaved { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Preview_SaveGif, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + f(.dismissWithoutContent) + + guard let strongSelf = self else { + return + } + + let context = strongSelf.context + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controllerInteraction = strongSelf.controllerInteraction + let _ = (toggleGifSaved(account: context.account, fileReference: FileMediaReference.savedGif(media: file), saved: true) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .generic: + controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + case let .limitExceeded(limit, premiumLimit): + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let text: String + if limit == premiumLimit || premiumConfiguration.isPremiumDisabled { + text = presentationData.strings.Premium_MaxSavedGifsFinalText + } else { + text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string + } + controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: false, action: { action in + if case .info = action { + let controller = PremiumIntroScreen(context: context, source: .savedGifs) + controllerInteraction?.navigationController()?.pushViewController(controller) + return true + } + return false + }), nil) + } + }) + }))) + } + + let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceView: sourceView, sourceRect: sourceRect)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) + strongSelf.controllerInteraction?.presentGlobalOverlayController(contextController, nil) + })*/ + } +} + +private final class ContextControllerContentSourceImpl: ContextControllerContentSource { + let controller: ViewController + weak var sourceView: UIView? + let sourceRect: CGRect + + let navigationController: NavigationController? = nil + + let passthroughTouches: Bool = false + + init(controller: ViewController, sourceView: UIView?, sourceRect: CGRect) { + self.controller = controller + self.sourceView = sourceView + self.sourceRect = sourceRect + } + + func transitionInfo() -> ContextControllerTakeControllerInfo? { + let sourceView = self.sourceView + let sourceRect = self.sourceRect + return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceView] in + if let sourceView = sourceView { + return (sourceView, sourceRect) + } else { + return nil + } + }) + } + + func animatedIn() { + if let controller = self.controller as? GalleryController { + controller.viewDidAppear(false) + } + } +} + +final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputViewAudioFeedback { + private let context: AccountContext + + public var insertText: ((NSAttributedString) -> Void)? + public var deleteBackwards: (() -> Void)? + public var switchToKeyboard: (() -> Void)? + public var presentController: ((ViewController) -> Void)? + + private var presentationData: PresentationData + private var inputNode: ChatEntityKeyboardInputNode? + private let animationCache: AnimationCache + private let animationRenderer: MultiAnimationRenderer + + init( + context: AccountContext, + isDark: Bool, + isSecret: Bool + ) { + self.context = context + + self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + self.animationRenderer = MultiAnimationRendererImpl() + + self.presentationData = context.sharedContext.currentPresentationData.with { $0 } + if isDark { + self.presentationData = self.presentationData.withUpdated(theme: defaultDarkPresentationTheme) + } + + //super.init(frame: CGRect(origin: CGPoint(), size: CGSize(width: 1.0, height: 1.0)), inputViewStyle: .default) + super.init(frame: CGRect(origin: CGPoint(), size: CGSize(width: 1.0, height: 1.0))) + + self.autoresizingMask = [.flexibleWidth, .flexibleHeight] + self.clipsToBounds = true + + let inputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak self] _, item, _, _, _ in + guard let strongSelf = self else { + return + } + let hasPremium = strongSelf.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: strongSelf.context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged + + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard let strongSelf = self else { + return + } + + if let file = item.file { + var text = "." + var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? + loop: for attribute in file.attributes { + switch attribute { + case let .CustomEmoji(_, displayText, packReference): + text = displayText + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + break loop + default: + break + } + } + + if file.isPremiumEmoji && !hasPremium { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + strongSelf.presentController?(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: presentationData.strings.EmojiInput_PremiumEmojiToast_Text, undoText: presentationData.strings.EmojiInput_PremiumEmojiToast_Action, customAction: { + guard let strongSelf = self else { + return + } + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + strongSelf.presentController?(controller) + }), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false })) + return + } + + if let emojiAttribute = emojiAttribute { + AudioServicesPlaySystemSound(0x450) + strongSelf.insertText?(NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: emojiAttribute])) + } + } else if let staticEmoji = item.staticEmoji { + AudioServicesPlaySystemSound(0x450) + strongSelf.insertText?(NSAttributedString(string: staticEmoji, attributes: [:])) + } + }) + }, + deleteBackwards: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.deleteBackwards?() + }, + openStickerSettings: { + }, + openFeatured: { + }, + addGroupAction: { _, _ in + }, + clearGroup: { _ in + }, + pushController: { _ in + }, + presentController: { _ in + }, + presentGlobalOverlayController: { _ in + }, + navigationController: { + return nil + }, + sendSticker: nil, + chatPeerId: nil + ) + + let semaphore = DispatchSemaphore(value: 0) + var emojiComponent: EmojiPagerContentComponent? + let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, isStandalone: true, isSecret: isSecret).start(next: { value in + emojiComponent = value + semaphore.signal() + }) + semaphore.wait() + + if let emojiComponent = emojiComponent { + let inputNode = ChatEntityKeyboardInputNode( + context: self.context, + currentInputData: ChatEntityKeyboardInputNode.InputData( + emoji: emojiComponent, + stickers: nil, + gifs: nil, + availableGifSearchEmojies: [] + ), + updatedInputData: .never(), + defaultToEmojiTab: true, + controllerInteraction: nil, + interfaceInteraction: nil, + chatPeerId: nil + ) + self.inputNode = inputNode + inputNode.emojiInputInteraction = inputInteraction + inputNode.externalTopPanelContainerImpl = nil + inputNode.switchToTextInput = { [weak self] in + self?.switchToKeyboard?() + } + self.addSubnode(inputNode) + } + } + + required init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func layoutSubviews() { + super.layoutSubviews() + + guard let inputNode = self.inputNode else { + return + } + + for view in self.subviews { + if view !== inputNode.view { + view.isHidden = true + } + } + + let bottomInset: CGFloat + if #available(iOS 11.0, *) { + bottomInset = max(0.0, UIScreen.main.bounds.height - (self.window?.safeAreaLayoutGuide.layoutFrame.maxY ?? 10000.0)) + } else { + bottomInset = 0.0 + } + + let presentationInterfaceState = ChatPresentationInterfaceState( + chatWallpaper: .builtin(WallpaperSettings()), + theme: self.presentationData.theme, + strings: self.presentationData.strings, + dateTimeFormat: self.presentationData.dateTimeFormat, + nameDisplayOrder: self.presentationData.nameDisplayOrder, + limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, + fontSize: self.presentationData.chatFontSize, + bubbleCorners: self.presentationData.chatBubbleCorners, + accountPeerId: self.context.account.peerId, + mode: .standard(previewing: false), + chatLocation: .peer(id: self.context.account.peerId), + subject: nil, + peerNearbyData: nil, + greetingData: nil, + pendingUnpinnedAllMessages: false, + activeGroupCallInfo: nil, + hasActiveGroupCall: false, + importState: nil + ) + + let _ = inputNode.updateLayout( + width: self.bounds.width, + leftInset: 0.0, + rightInset: 0.0, + bottomInset: bottomInset, + standardInputHeight: self.bounds.height, + inputHeight: self.bounds.height, + maximumHeight: self.bounds.height, + inputPanelHeight: 0.0, + transition: .immediate, + interfaceState: presentationInterfaceState, + deviceMetrics: DeviceMetrics.iPhone12, + isVisible: true, + isExpanded: false + ) + inputNode.frame = self.bounds + } +} diff --git a/submodules/TelegramUI/Sources/ChatFeedNavigationInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatFeedNavigationInputPanelNode.swift index a81a9e812e..f815821911 100644 --- a/submodules/TelegramUI/Sources/ChatFeedNavigationInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatFeedNavigationInputPanelNode.swift @@ -54,7 +54,7 @@ final class ChatFeedNavigationInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.navigateFeed() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState } diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 19bfb4cdf8..1d0e5c9275 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -71,7 +71,8 @@ func chatHistoryEntriesForView( media: [TelegramMediaAction(action: .joinedByRequest)], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) } @@ -134,7 +135,9 @@ func chatHistoryEntriesForView( } if presentationData.largeEmoji, message.media.isEmpty { - if stickersEnabled && message.text.count == 1, let _ = associatedData.animatedEmojiStickers[message.text.basicEmoji.0], (message.textEntitiesAttribute?.entities.isEmpty ?? true) { + if stickersEnabled && message.text.count == 1, let entities = message.textEntitiesAttribute?.entities, entities.count == 1, case let .CustomEmoji(_, fileId) = entities[0].type, let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile, !file.isVideoEmoji { + contentTypeHint = .animatedEmoji + } else if stickersEnabled && message.text.count == 1, let _ = associatedData.animatedEmojiStickers[message.text.basicEmoji.0], (message.textEntitiesAttribute?.entities.isEmpty ?? true) { contentTypeHint = .animatedEmoji } else if message.text.count < 10 && messageIsElligibleForLargeEmoji(message) { contentTypeHint = .largeEmoji @@ -323,7 +326,8 @@ func chatHistoryEntriesForView( media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, - associatedMessageIds: message.associatedMessageIds + associatedMessageIds: message.associatedMessageIds, + associatedMedia: message.associatedMedia ) nextAdMessageId += 1 entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false))) diff --git a/submodules/TelegramUI/Sources/ChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/ChatInputContextPanelNode.swift index 9cf93a9c9c..d669d813d4 100644 --- a/submodules/TelegramUI/Sources/ChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputContextPanelNode.swift @@ -20,7 +20,7 @@ class ChatInputContextPanelNode: ASDisplayNode { var theme: PresentationTheme var fontSize: PresentationFontSize - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.context = context self.theme = theme self.fontSize = fontSize diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index 0b955aecc1..1aa38814f0 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -11,7 +11,20 @@ class ChatInputNode: ASDisplayNode { return .single(Void()) } - func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) { + var externalTopPanelContainer: UIView? { + return nil + } + + var topBackgroundExtension: CGFloat = 0.0 + var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? + + var hideInput: Bool = false + var adjustLayoutForHiddenInput: Bool = false + var hideInputUpdated: ((ContainedViewLayoutTransition) -> Void)? + + var followsDefaultHeight: Bool = false + + func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) { return (0.0, 0.0) } } diff --git a/submodules/TelegramUI/Sources/ChatInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatInputPanelNode.swift index 52001cf08b..659fa7acb2 100644 --- a/submodules/TelegramUI/Sources/ChatInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputPanelNode.swift @@ -15,7 +15,7 @@ class ChatInputPanelNode: ASDisplayNode { func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) { } - func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { return 0.0 } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContextPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContextPanels.swift index ddc5922a60..a41ea42c4f 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContextPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContextPanels.swift @@ -25,7 +25,7 @@ private func inputQueryResultPriority(_ result: ChatPresentationInputQueryResult } } -func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputContextPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> ChatInputContextPanelNode? { +func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputContextPanelNode?, controllerInteraction: ChatControllerInteraction, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPresentationContext: ChatPresentationContext) -> ChatInputContextPanelNode? { guard let _ = chatPresentationInterfaceState.renderedPeer?.peer else { return nil } @@ -34,7 +34,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa if let currentPanel = currentPanel as? CommandMenuChatInputContextPanelNode { return currentPanel } else { - let panel = CommandMenuChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, peerId: renderedPeer.peerId) + let panel = CommandMenuChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, peerId: renderedPeer.peerId, chatPresentationContext: chatPresentationContext) panel.interfaceInteraction = interfaceInteraction return panel } @@ -68,7 +68,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa if let currentPanel = currentPanel as? DisabledContextResultsChatInputContextPanelNode { return currentPanel } else { - let panel = DisabledContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = DisabledContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: controllerInteraction.presentationContext) panel.interfaceInteraction = interfaceInteraction return panel } @@ -86,7 +86,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(results: results.map({ $0.file }), query: query) return currentPanel } else { - let panel = InlineReactionSearchPanel(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, peerId: chatPresentationInterfaceState.renderedPeer?.peerId) + let panel = InlineReactionSearchPanel(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, peerId: chatPresentationInterfaceState.renderedPeer?.peerId, chatPresentationContext: chatPresentationContext) panel.controllerInteraction = controllerInteraction panel.interfaceInteraction = interfaceInteraction panel.updateResults(results: results.map({ $0.file }), query: query) @@ -99,7 +99,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(results) return currentPanel } else { - let panel = HashtagChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = HashtagChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: controllerInteraction.presentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(results) return panel @@ -111,7 +111,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(results) return currentPanel } else { - let panel = EmojisChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = EmojisChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: chatPresentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(results) return panel @@ -123,7 +123,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(peers) return currentPanel } else { - let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .input) + let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .input, chatPresentationContext: chatPresentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(peers) return panel @@ -137,7 +137,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(commands) return currentPanel } else { - let panel = CommandChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = CommandChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: controllerInteraction.presentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(commands) return panel @@ -153,7 +153,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(results) return currentPanel } else { - let panel = VerticalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = VerticalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: controllerInteraction.presentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(results) return panel @@ -163,7 +163,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa currentPanel.updateResults(results) return currentPanel } else { - let panel = HorizontalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize) + let panel = HorizontalListContextResultsChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, chatPresentationContext: controllerInteraction.presentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(results) return panel @@ -177,7 +177,7 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa return nil } -func chatOverlayContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputContextPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> ChatInputContextPanelNode? { +func chatOverlayContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputContextPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPresentationContext: ChatPresentationContext) -> ChatInputContextPanelNode? { guard let searchQuerySuggestionResult = chatPresentationInterfaceState.searchQuerySuggestionResult, let _ = chatPresentationInterfaceState.renderedPeer?.peer else { return nil } @@ -189,7 +189,7 @@ func chatOverlayContextPanelForChatPresentationIntefaceState(_ chatPresentationI currentPanel.updateResults(peers) return currentPanel } else { - let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .search) + let panel = MentionChatInputContextPanelNode(context: context, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, mode: .search, chatPresentationContext: chatPresentationContext) panel.interfaceInteraction = interfaceInteraction panel.updateResults(peers) return panel diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 2e95f80d98..788133b528 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -7,6 +7,8 @@ import AccountContext import Emoji import ChatInterfaceState import ChatPresentationInterfaceState +import SwiftSignalKit +import TextFormat struct PossibleContextQueryTypes: OptionSet { var rawValue: Int32 @@ -109,7 +111,9 @@ func textInputStateContextQueryRangeAndType(_ inputState: ChatTextInputState) -> let string = (inputString as String) let trimmedString = string.trimmingTrailingSpaces() if string.count < 3, trimmedString.isSingleEmoji { - return [(NSRange(location: 0, length: inputString.length - (string.count - trimmedString.count)), [.emoji], nil)] + if inputText.attribute(ChatTextInputAttributes.customEmoji, at: 0, effectiveRange: nil) == nil { + return [(NSRange(location: 0, length: inputString.length - (string.count - trimmedString.count)), [.emoji], nil)] + } } var possibleTypes = PossibleContextQueryTypes([.command, .mention, .hashtag, .emojiSearch]) @@ -173,6 +177,49 @@ func textInputStateContextQueryRangeAndType(_ inputState: ChatTextInputState) -> return results } +func serviceTasksForChatPresentationIntefaceState(context: AccountContext, chatPresentationInterfaceState: ChatPresentationInterfaceState, updateState: @escaping ((ChatPresentationInterfaceState) -> ChatPresentationInterfaceState) -> Void) -> [AnyHashable: () -> Disposable] { + var missingEmoji = Set() + let inputText = chatPresentationInterfaceState.interfaceState.composeInputState.inputText + inputText.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: inputText.length), using: { value, _, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + if value.file == nil { + missingEmoji.insert(value.fileId) + } + } + }) + + var result: [AnyHashable: () -> Disposable] = [:] + for id in missingEmoji { + result["emoji-\(id)"] = { + return (context.engine.stickers.resolveInlineStickers(fileIds: [id]) + |> deliverOnMainQueue).start(next: { result in + if let file = result[id] { + updateState({ state -> ChatPresentationInterfaceState in + return state.updatedInterfaceState { interfaceState -> ChatInterfaceState in + var inputState = interfaceState.composeInputState + let text = NSMutableAttributedString(attributedString: inputState.inputText) + + inputState.inputText.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: inputText.length), using: { value, range, _ in + if let value = value as? ChatTextInputTextCustomEmojiAttribute { + if value.fileId == id { + text.removeAttribute(ChatTextInputAttributes.customEmoji, range: range) + text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: file.fileId.id, file: file), range: range) + } + } + }) + + inputState.inputText = text + + return interfaceState.withUpdatedComposeInputState(inputState) + } + }) + } + }) + } + } + return result +} + func inputContextQueriesForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState) -> [ChatPresentationInputQuery] { let inputState = chatPresentationInterfaceState.interfaceState.effectiveInputState let inputString: NSString = inputState.inputText.string as NSString @@ -267,13 +314,15 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte switch chatPresentationInterfaceState.inputMode { case .media: - accessoryItems.append(.keyboard) + accessoryItems.append(.input(isEnabled: true, inputMode: .keyboard)) return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .inputButtons: - return ChatTextInputPanelState(accessoryItems: [.keyboard], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) + return ChatTextInputPanelState(accessoryItems: [.botInput(isEnabled: true, inputMode: .keyboard)], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .none, .text: if let _ = chatPresentationInterfaceState.interfaceState.editMessage { - return ChatTextInputPanelState(accessoryItems: [], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) + accessoryItems.append(.input(isEnabled: true, inputMode: .emoji)) + + return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) } else { var accessoryItems: [ChatTextInputAccessoryItem] = [] var extendedSearchLayout = false @@ -302,6 +351,9 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte } var stickersEnabled = true + + let stickersAreEmoji = !isTextEmpty + if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel { if isTextEmpty, case .broadcast = peer.info, canSendMessagesToPeer(peer) { accessoryItems.append(.silentPost(chatPresentationInterfaceState.interfaceState.silentPosting)) @@ -317,15 +369,15 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte if isTextEmpty && chatPresentationInterfaceState.hasBots && chatPresentationInterfaceState.hasBotCommands { accessoryItems.append(.commands) } - #if DEBUG - accessoryItems.append(.stickers(stickersEnabled)) - #else - if isTextEmpty { - accessoryItems.append(.stickers(stickersEnabled)) + + if stickersEnabled { + accessoryItems.append(.input(isEnabled: true, inputMode: stickersAreEmoji ? .emoji : .stickers)) + } else { + accessoryItems.append(.input(isEnabled: true, inputMode: .emoji)) } - #endif + if isTextEmpty, let message = chatPresentationInterfaceState.keyboardButtonsMessage, let _ = message.visibleButtonKeyboardMarkup, chatPresentationInterfaceState.interfaceState.messageActionsState.dismissedButtonKeyboardMessageId != message.id { - accessoryItems.append(.inputButtons) + accessoryItems.append(.botInput(isEnabled: true, inputMode: .bot)) } } return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift index 71007c4caa..a988e0bdc1 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift @@ -6,12 +6,24 @@ import Postbox import AccountContext import ChatPresentationInterfaceState -func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentNode: ChatInputNode?, interfaceInteraction: ChatPanelInterfaceInteraction?, inputMediaNode: ChatMediaInputNode?, controllerInteraction: ChatControllerInteraction, inputPanelNode: ChatInputPanelNode?) -> ChatInputNode? { +func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentNode: ChatInputNode?, interfaceInteraction: ChatPanelInterfaceInteraction?, inputMediaNode: ChatMediaInputNode?, controllerInteraction: ChatControllerInteraction, inputPanelNode: ChatInputPanelNode?, makeMediaInputNode: () -> ChatInputNode?) -> ChatInputNode? { if !(inputPanelNode is ChatTextInputPanelNode) { return nil } switch chatPresentationInterfaceState.inputMode { - case .media: + case .media: + if "".isEmpty { + if let currentNode = currentNode as? ChatEntityKeyboardInputNode { + return currentNode + } else if let inputMediaNode = inputMediaNode { + return inputMediaNode + } else if let inputMediaNode = makeMediaInputNode() { + inputMediaNode.interfaceInteraction = interfaceInteraction + return inputMediaNode + } else { + return nil + } + } else { if let currentNode = currentNode as? ChatMediaInputNode { return currentNode } else if let inputMediaNode = inputMediaNode { @@ -39,19 +51,20 @@ func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: inputNode.interfaceInteraction = interfaceInteraction return inputNode } - case .inputButtons: - if chatPresentationInterfaceState.forceInputCommandsHidden { - return nil - } else { - if let currentNode = currentNode as? ChatButtonKeyboardInputNode { - return currentNode - } else { - let inputNode = ChatButtonKeyboardInputNode(context: context, controllerInteraction: controllerInteraction) - inputNode.interfaceInteraction = interfaceInteraction - return inputNode - } - } - case .none, .text: + } + case .inputButtons: + if chatPresentationInterfaceState.forceInputCommandsHidden { return nil + } else { + if let currentNode = currentNode as? ChatButtonKeyboardInputNode { + return currentNode + } else { + let inputNode = ChatButtonKeyboardInputNode(context: context, controllerInteraction: controllerInteraction) + inputNode.interfaceInteraction = interfaceInteraction + return inputNode + } + } + case .none, .text: + return nil } } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift index 54f4784e65..7e5e257aa2 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift @@ -5,7 +5,7 @@ import TelegramCore import AccountContext import ChatPresentationInterfaceState -func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: AccessoryPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> AccessoryPanelNode? { +func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: AccessoryPanelNode?, chatControllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> AccessoryPanelNode? { if let _ = chatPresentationInterfaceState.interfaceState.selectionState { return nil } @@ -39,7 +39,7 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS editPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings) return editPanelNode } else { - let panelNode = EditAccessoryPanelNode(context: context, messageId: editMessage.messageId, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat) + let panelNode = EditAccessoryPanelNode(context: context, messageId: editMessage.messageId, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer) panelNode.interfaceInteraction = interfaceInteraction return panelNode } @@ -60,7 +60,7 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS forwardPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, forwardOptionsState: chatPresentationInterfaceState.interfaceState.forwardOptionsState) return forwardPanelNode } else { - let panelNode = ForwardAccessoryPanelNode(context: context, messageIds: forwardMessageIds, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, forwardOptionsState: chatPresentationInterfaceState.interfaceState.forwardOptionsState) + let panelNode = ForwardAccessoryPanelNode(context: context, messageIds: forwardMessageIds, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, fontSize: chatPresentationInterfaceState.fontSize, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, forwardOptionsState: chatPresentationInterfaceState.interfaceState.forwardOptionsState, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer) panelNode.interfaceInteraction = interfaceInteraction return panelNode } @@ -70,7 +70,7 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS replyPanelNode.updateThemeAndStrings(theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings) return replyPanelNode } else { - let panelNode = ReplyAccessoryPanelNode(context: context, messageId: replyMessageId, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat) + let panelNode = ReplyAccessoryPanelNode(context: context, messageId: replyMessageId, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer) panelNode.interfaceInteraction = interfaceInteraction return panelNode } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index dd4b428af1..49e08d6c23 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -691,7 +691,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState let id = Int64.random(in: Int64.min ... Int64.max) let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")]) - let message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start() } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index 6a5ce76378..4971c3243e 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -341,21 +341,63 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee ) } } + + let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged return signal - |> map { keywords -> [(String, String)] in - var result: [(String, String)] = [] - for keyword in keywords { - for emoticon in keyword.emoticons { - result.append((emoticon, keyword.keyword)) - } - } - return result - } - |> map { result -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in - return { _ in return .emojis(result, range) } - } |> castError(ChatContextQueryError.self) + |> mapToSignal { keywords -> Signal<(ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult?, ChatContextQueryError> in + return combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + hasPremium + ) + |> map { view, hasPremium -> [(String, TelegramMediaFile?, String)] in + var result: [(String, TelegramMediaFile?, String)] = [] + + var allEmoticons: [String: String] = [:] + for keyword in keywords { + for emoticon in keyword.emoticons { + allEmoticons[emoticon] = keyword.keyword + } + } + + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + for attribute in item.file.attributes { + switch attribute { + case let .CustomEmoji(_, alt, _): + if !alt.isEmpty, let keyword = allEmoticons[alt] { + if !item.file.isPremiumEmoji || hasPremium { + result.append((alt, item.file, keyword)) + } + } + default: + break + } + } + } + + for keyword in keywords { + for emoticon in keyword.emoticons { + result.append((emoticon, nil, keyword.keyword)) + } + } + return result + } + |> map { result -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in + return { _ in return .emojis(result, range) } + } + |> castError(ChatContextQueryError.self) + } } } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift index 033774677c..90a7d71ad8 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift @@ -297,7 +297,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState textInputPanelNode.context = context return (textInputPanelNode, nil) } else { - let panel = ChatTextInputPanelNode(presentationInterfaceState: chatPresentationInterfaceState, presentationContext: nil, presentController: { [weak interfaceInteraction] controller in + let panel = ChatTextInputPanelNode(context: context, presentationInterfaceState: chatPresentationInterfaceState, presentationContext: nil, presentController: { [weak interfaceInteraction] controller in interfaceInteraction?.presentController(controller, nil) }) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift index 2059729571..94007aeba6 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceTitlePanelNodes.swift @@ -4,7 +4,7 @@ import TelegramCore import AccountContext import ChatPresentationInterfaceState -func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> ChatTitleAccessoryPanelNode? { +func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> ChatTitleAccessoryPanelNode? { if case .overlay = chatPresentationInterfaceState.mode { return nil } @@ -90,7 +90,7 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat if let currentPanel = currentPanel as? ChatPinnedMessageTitlePanelNode { return currentPanel } else { - let panel = ChatPinnedMessageTitlePanelNode(context: context) + let panel = ChatPinnedMessageTitlePanelNode(context: context, animationCache: controllerInteraction?.presentationContext.animationCache, animationRenderer: controllerInteraction?.presentationContext.animationRenderer) panel.interfaceInteraction = interfaceInteraction return panel } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift index 3468153e01..f8d1b0a914 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift @@ -236,9 +236,9 @@ final class ChatMediaInputGifPane: ChatMediaInputPane, UIScrollViewDelegate { multiplexedNode.fileSelected = { [weak self] file, sourceNode, sourceRect in if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, false) + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode.view, sourceRect, false) } else { - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode, sourceRect, false, false) + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, false) } } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index f4758dc9e0..bfef93a510 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -11,6 +11,7 @@ import TelegramNotices import MergeLists import AccountContext import StickerPackPreviewUI +import StickerPeekUI import PeerInfoUI import SettingsUI import ContextUI @@ -577,7 +578,7 @@ final class ChatMediaInputNode: ChatInputNode { var requestDisableStickerAnimations: ((Bool) -> Void)? - private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, ChatPresentationInterfaceState, DeviceMetrics, Bool)? + private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, CGFloat, ChatPresentationInterfaceState, DeviceMetrics, Bool, Bool)? private var paneArrangement: ChatMediaInputPaneArrangement private var initializedArrangement = false @@ -796,7 +797,7 @@ final class ChatMediaInputNode: ChatInputNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -864,7 +865,7 @@ final class ChatMediaInputNode: ChatInputNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -958,7 +959,7 @@ final class ChatMediaInputNode: ChatInputNode { getItemIsPreviewedImpl = { [weak self] item in if let strongSelf = self { - return strongSelf.inputNodeInteraction.previewedStickerPackItem == .pack(item) + return strongSelf.inputNodeInteraction.previewedStickerPackItem == .pack(item.file) } return false } @@ -1096,7 +1097,7 @@ final class ChatMediaInputNode: ChatInputNode { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -1455,7 +1456,7 @@ final class ChatMediaInputNode: ChatInputNode { } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in }, baseNavigationController: nil) @@ -1467,13 +1468,13 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in f(.default) if isSaved { - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode, sourceRect, false, false) + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, false) } else if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, false) + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode.view, sourceRect, false) } }))) - if let (_, _, _, _, _, _, _, _, interfaceState, _, _) = strongSelf.validLayout { + if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { var isScheduledMessages = false if case .scheduledMessages = interfaceState.subject { isScheduledMessages = true @@ -1486,9 +1487,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in f(.default) if isSaved { - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode, sourceRect, true, false) + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, true, false) } else if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, true) + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode.view, sourceRect, true) } }))) } @@ -1499,7 +1500,7 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in f(.default) - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode, sourceRect, false, true) + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, true) }))) } } @@ -1592,10 +1593,10 @@ final class ChatMediaInputNode: ChatInputNode { if let item = item as? StickerPreviewPeekItem { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] - if let (_, _, _, _, _, _, _, _, interfaceState, _, _) = strongSelf.validLayout { + if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { var isScheduledMessages = false if case .scheduledMessages = interfaceState.subject { isScheduledMessages = true @@ -1608,9 +1609,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode, animationNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1622,9 +1623,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode, animationNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1642,7 +1643,7 @@ final class ChatMediaInputNode: ChatInputNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -1651,7 +1652,7 @@ final class ChatMediaInputNode: ChatInputNode { } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -1678,7 +1679,7 @@ final class ChatMediaInputNode: ChatInputNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -1694,7 +1695,7 @@ final class ChatMediaInputNode: ChatInputNode { } } }))) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: item, menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: item, menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -1744,10 +1745,10 @@ final class ChatMediaInputNode: ChatInputNode { } ) |> deliverOnMainQueue - |> map { isStarred, hasPremium -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred, hasPremium -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] - if let (_, _, _, _, _, _, _, _, interfaceState, _, _) = strongSelf.validLayout { + if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { var isScheduledMessages = false if case .scheduledMessages = interfaceState.subject { isScheduledMessages = true @@ -1760,9 +1761,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode, animationNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1774,9 +1775,9 @@ final class ChatMediaInputNode: ChatInputNode { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode, animationNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1795,7 +1796,7 @@ final class ChatMediaInputNode: ChatInputNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -1804,7 +1805,7 @@ final class ChatMediaInputNode: ChatInputNode { } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -1832,7 +1833,7 @@ final class ChatMediaInputNode: ChatInputNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, updatedPresentationData: strongSelf.controllerInteraction.updatedPresentationData, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -1849,7 +1850,7 @@ final class ChatMediaInputNode: ChatInputNode { } })) ) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -1866,11 +1867,11 @@ final class ChatMediaInputNode: ChatInputNode { } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = PeekController(presentationData: presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) controller.visibilityUpdated = { [weak self] visible in self?.previewingStickersPromise.set(visible) @@ -1922,8 +1923,8 @@ final class ChatMediaInputNode: ChatInputNode { self.paneArrangement = self.paneArrangement.withIndexTransition(0.0).withCurrentIndex(index) let updatedGifPanelWasActive = self.paneArrangement.panes[self.paneArrangement.currentIndex] == .gifs - if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.validLayout { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: transition, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible) + if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.validLayout { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: transition, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) self.updateAppearanceTransition(transition: transition) } if updatedGifPanelWasActive != previousGifPanelWasActive { @@ -1940,8 +1941,8 @@ final class ChatMediaInputNode: ChatInputNode { } } } else { - if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.validLayout { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .animated(duration: 0.25, curve: .spring), interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible) + if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.validLayout { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .animated(duration: 0.25, curve: .spring), interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) } } } @@ -2179,20 +2180,20 @@ final class ChatMediaInputNode: ChatInputNode { } func simulateUpdateLayout(isVisible: Bool) { - if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, _) = self.validLayout { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible) + if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, _, isExpanded) = self.validLayout { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool) -> (CGFloat, CGFloat) { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) { var searchMode: ChatMediaInputSearchMode? - if let (_, _, _, _, _, _, _, _, interfaceState, _, _) = self.validLayout, case let .media(_, maybeExpanded, _) = interfaceState.inputMode, let expanded = maybeExpanded, case let .search(mode) = expanded { + if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = self.validLayout, case let .media(_, maybeExpanded, _) = interfaceState.inputMode, let expanded = maybeExpanded, case let .search(mode) = expanded { searchMode = mode } let wasVisible = self.validLayout?.10 ?? false - self.validLayout = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) + self.validLayout = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) if self.theme !== interfaceState.theme || self.strings !== interfaceState.strings { self.updateThemeAndStrings(chatWallpaper: interfaceState.chatWallpaper, theme: interfaceState.theme, strings: interfaceState.strings) @@ -2545,7 +2546,7 @@ final class ChatMediaInputNode: ChatInputNode { self.stickerPane.removeFromSupernode() } case .changed: - if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.validLayout { + if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.validLayout { let translationX = -recognizer.translation(in: self.view).x var indexTransition = translationX / width if self.paneArrangement.currentIndex == 0 { @@ -2554,10 +2555,10 @@ final class ChatMediaInputNode: ChatInputNode { indexTransition = min(0.0, indexTransition) } self.paneArrangement = self.paneArrangement.withIndexTransition(indexTransition) - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible) + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .immediate, interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) } case .ended: - if let (width, _, _, _, _, _, _, _, _, _, _) = self.validLayout { + if let (width, _, _, _, _, _, _, _, _, _, _, _) = self.validLayout { var updatedIndex = self.paneArrangement.currentIndex if abs(self.paneArrangement.indexTransition * width) > 30.0 { if self.paneArrangement.indexTransition < 0.0 { @@ -2570,9 +2571,9 @@ final class ChatMediaInputNode: ChatInputNode { self.setCurrentPane(self.paneArrangement.panes[updatedIndex], transition: .animated(duration: 0.25, curve: .spring)) } case .cancelled: - if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.validLayout { + if let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.validLayout { self.paneArrangement = self.paneArrangement.withIndexTransition(0.0) - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .animated(duration: 0.25, curve: .spring), interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible) + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, standardInputHeight: standardInputHeight, inputHeight: inputHeight, maximumHeight: maximumHeight, inputPanelHeight: inputPanelHeight, transition: .animated(duration: 0.25, curve: .spring), interfaceState: interfaceState, deviceMetrics: deviceMetrics, isVisible: isVisible, isExpanded: isExpanded) } default: break @@ -2734,7 +2735,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceRect = self.sourceRect return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceRect) + return (sourceNode.view, sourceRect) } else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index f06f403ee9..47635290c9 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -74,7 +74,7 @@ final class ChatMediaInputStickerGridSectionNode: ASDisplayNode { self.setupNode = setupNode case .clear: let setupNode = HighlightableButtonNode() - setupNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme), for: []) + setupNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.stickersSectionTextColor), for: []) self.setupNode = setupNode } @@ -412,7 +412,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { if let interfaceInteraction = self.interfaceInteraction, let (_, item, _) = self.currentState, case .ended = recognizer.state { if let isLocked = self.isLocked, isLocked { } else { - let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, false, nil, false, self, self.bounds) + let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, false, nil, false, self.view, self.bounds, nil) self.imageNode.layer.animateAlpha(from: 0.5, to: 1.0, duration: 1.0) } } @@ -454,7 +454,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { func updatePreviewing(animated: Bool) { var isPreviewing = false if let (_, item, _) = self.currentState, let interaction = self.inputNodeInteraction { - isPreviewing = interaction.previewedStickerPackItem == .pack(item) + isPreviewing = interaction.previewedStickerPackItem == .pack(item.file) } if self.currentIsPreviewing != isPreviewing { self.currentIsPreviewing = isPreviewing diff --git a/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift b/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift index 2f102ab512..1b0375f792 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputTrendingPane.swift @@ -326,7 +326,7 @@ final class ChatMediaInputTrendingPane: ChatMediaInputPane { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 92919b03df..c4773edf75 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -18,13 +18,14 @@ import TelegramUniversalVideoContent import GalleryUI import WallpaperBackgroundNode import InvisibleInkDustNode +import TextNodeWithEntities private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId) -> NSAttributedString? { return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false) } class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { - let labelNode: TextNode + let labelNode: TextNodeWithEntities private var dustNode: InvisibleInkDustNode? var backgroundNode: WallpaperBubbleBackgroundNode? var backgroundColorNode: ASDisplayNode @@ -41,10 +42,28 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { private var cachedMaskBackgroundImage: (CGPoint, UIImage, [CGRect])? private var absoluteRect: (CGRect, CGSize)? + override var visibility: ListViewItemNodeVisibility { + didSet { + if oldValue != self.visibility { + switch self.visibility { + case .none: + self.labelNode.visibilityRect = nil + //self.spoilerTextNode?.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + self.labelNode.visibilityRect = subRect + //self.spoilerTextNode?.visibilityRect = subRect + } + } + } + } + required init() { - self.labelNode = TextNode() - self.labelNode.isUserInteractionEnabled = false - self.labelNode.displaysAsynchronously = false + self.labelNode = TextNodeWithEntities() + self.labelNode.textNode.isUserInteractionEnabled = false + self.labelNode.textNode.displaysAsynchronously = false self.backgroundColorNode = ASDisplayNode() self.backgroundMaskNode = ASImageNode() @@ -55,7 +74,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { super.init() - self.addSubnode(self.labelNode) + self.addSubnode(self.labelNode.textNode) } required init?(coder aDecoder: NSCoder) { @@ -130,7 +149,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { } override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { - let makeLabelLayout = TextNode.asyncLayout(self.labelNode) + let makeLabelLayout = TextNodeWithEntities.asyncLayout(self.labelNode) let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage @@ -273,10 +292,16 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { videoNode.removeFromSupernode() } - let _ = apply() + let _ = apply(TextNodeWithEntities.Arguments( + context: item.context, + cache: item.controllerInteraction.presentationContext.animationCache, + renderer: item.controllerInteraction.presentationContext.animationRenderer, + placeholderColor: item.presentationData.theme.theme.chat.message.freeform.withWallpaper.reactionInactiveBackground, + attemptSynchronous: synchronousLoads + )) let labelFrame = CGRect(origin: CGPoint(x: 8.0, y: image != nil ? 2 : floorToScreenPixels((backgroundSize.height - labelLayout.size.height) / 2.0) - 1.0), size: labelLayout.size) - strongSelf.labelNode.frame = labelFrame + strongSelf.labelNode.textNode.frame = labelFrame strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) if !labelLayout.spoilers.isEmpty { @@ -289,7 +314,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { dustNode = InvisibleInkDustNode(textNode: nil) dustNode.isUserInteractionEnabled = false strongSelf.dustNode = dustNode - strongSelf.insertSubnode(dustNode, aboveSubnode: strongSelf.labelNode) + strongSelf.insertSubnode(dustNode, aboveSubnode: strongSelf.labelNode.textNode) } dustNode.frame = labelFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 1.0) dustNode.update(size: dustNode.frame.size, color: dustColor, textColor: dustColor, rects: labelLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: labelLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }) @@ -333,6 +358,18 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.backgroundColorNode.frame = CGRect(origin: CGPoint(), size: image.size) strongSelf.cachedMaskBackgroundImage = (offset, image, labelRects) + + switch strongSelf.visibility { + case .none: + strongSelf.labelNode.visibilityRect = nil + //strongSelf.spoilerTextNode?.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + strongSelf.labelNode.visibilityRect = subRect + //strongSelf.spoilerTextNode?.visibilityRect = subRect + } } } }) @@ -367,9 +404,9 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { override func updateTouchesAtPoint(_ point: CGPoint?) { if let item = self.item { var rects: [(CGRect, CGRect)]? - let textNodeFrame = self.labelNode.frame + let textNodeFrame = self.labelNode.textNode.frame if let point = point { - if let (index, attributes) = self.labelNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)) { + if let (index, attributes) = self.labelNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)) { let possibleNames: [String] = [ TelegramTextAttributes.URL, TelegramTextAttributes.PeerMention, @@ -379,7 +416,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { ] for name in possibleNames { if let _ = attributes[NSAttributedString.Key(rawValue: name)] { - rects = self.labelNode.lineAndAttributeRects(name: name, at: index) + rects = self.labelNode.textNode.lineAndAttributeRects(name: name, at: index) break } } @@ -403,9 +440,9 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { linkHighlightingNode = LinkHighlightingNode(color: serviceColor.linkHighlight) linkHighlightingNode.inset = 2.5 self.linkHighlightingNode = linkHighlightingNode - self.insertSubnode(linkHighlightingNode, belowSubnode: self.labelNode) + self.insertSubnode(linkHighlightingNode, belowSubnode: self.labelNode.textNode) } - linkHighlightingNode.frame = self.labelNode.frame.offsetBy(dx: 0.0, dy: 1.5) + linkHighlightingNode.frame = self.labelNode.textNode.frame.offsetBy(dx: 0.0, dy: 1.5) linkHighlightingNode.updateRects(mappedRects) } else if let linkHighlightingNode = self.linkHighlightingNode { self.linkHighlightingNode = nil @@ -417,11 +454,11 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { } override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction { - let textNodeFrame = self.labelNode.frame - if let (index, attributes) = self.labelNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)), gesture == .tap { + let textNodeFrame = self.labelNode.textNode.frame + if let (index, attributes) = self.labelNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)), gesture == .tap { if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { var concealed = true - if let (attributeText, fullText) = self.labelNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { + if let (attributeText, fullText) = self.labelNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText) } return .url(url: url, concealed: concealed) diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 2d6e5d2fdf..7673f8f510 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -407,6 +407,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if self.visibilityStatus != oldValue { self.updateVisibility() self.haptic?.enabled = self.visibilityStatus == true + + self.replyInfoNode?.visibility = self.visibilityStatus == true } } } @@ -423,7 +425,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if !item.message.effectivelyIncoming(item.context.account.peerId) { animationNode.success = { [weak self] onlyHaptic in if let strongSelf = self, let item = strongSelf.item { - item.controllerInteraction.animateDiceSuccess(onlyHaptic) + item.controllerInteraction.animateDiceSuccess(true, !onlyHaptic) } } } @@ -433,7 +435,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if !item.message.effectivelyIncoming(item.context.account.peerId) { animationNode.success = { [weak self] in if let strongSelf = self, let item = strongSelf.item { - item.controllerInteraction.animateDiceSuccess(false) + item.controllerInteraction.animateDiceSuccess(true, true) } } } @@ -518,9 +520,17 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } else if self.telegramFile == nil && self.telegramDice == nil { let (emoji, fitz) = item.message.text.basicEmoji - var emojiFile: TelegramMediaFile? - emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file + var emojiFile: TelegramMediaFile? + if let entities = item.message.textEntitiesAttribute?.entities, entities.count == 1, case let .CustomEmoji(_, fileId) = entities[0].type { + if let file = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile { + emojiFile = file + } + } + + if emojiFile == nil { + emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file + } if emojiFile == nil { emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file } @@ -547,10 +557,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } var animationItems: [Int: StickerPackItem]? - if let items = item.associatedData.additionalAnimatedEmojiStickers[textEmoji] { - animationItems = items - } else if let items = item.associatedData.additionalAnimatedEmojiStickers[additionalTextEmoji] { - animationItems = items + if let emojiFile = emojiFile, emojiFile.isCustomEmoji { + } else { + if let items = item.associatedData.additionalAnimatedEmojiStickers[textEmoji] { + animationItems = items + } else if let items = item.associatedData.additionalAnimatedEmojiStickers[additionalTextEmoji] { + animationItems = items + } } if let animationItems = animationItems { @@ -580,16 +593,18 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { playbackMode = .once } } else if let emojiFile = self.emojiFile { - isEmoji = true file = emojiFile - //if alreadySeen && emojiFile.resource is LocalFileReferenceMediaResource { + + if emojiFile.isCustomEmoji { + playbackMode = .loop + } else { + isEmoji = true playbackMode = .still(.end) - //} else { - // playbackMode = .once - //} - let (_, fitz) = item.message.text.basicEmoji - if let fitz = fitz { - fitzModifier = EmojiFitzModifier(emoji: fitz) + + let (_, fitz) = item.message.text.basicEmoji + if let fitz = fitz { + fitzModifier = EmojiFitzModifier(emoji: fitz) + } } } @@ -975,7 +990,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let (dateAndStatusSize, dateAndStatusApply) = statusSuggestedWidthAndContinue.1(statusSuggestedWidthAndContinue.0) var viaBotApply: (TextNodeLayout, () -> TextNode)? - var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? + var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)? var needsReplyBackground = false var replyMarkup: ReplyMarkupMessageAttribute? @@ -1017,7 +1032,17 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId { } else { - replyInfoApply = makeReplyInfoLayout(item.presentationData, item.presentationData.strings, item.context, .standalone, replyMessage, item.message, CGSize(width: availableContentWidth, height: CGFloat.greatestFiniteMagnitude)) + replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments( + presentationData: item.presentationData, + strings: item.presentationData.strings, + context: item.context, + type: .standalone, + message: replyMessage, + parentMessage: item.message, + constrainedSize: CGSize(width: availableContentWidth, height: CGFloat.greatestFiniteMagnitude), + animationCache: item.controllerInteraction.presentationContext.animationCache, + animationRenderer: item.controllerInteraction.presentationContext.animationRenderer + )) } } else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty { replyMarkup = attribute @@ -1135,7 +1160,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { layoutSize.height += 4.0 + reactionButtonsSizeAndApply.0.height } - return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, _ in + return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, synchronousLoads in if let strongSelf = self { strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature) strongSelf.updateAccessibilityData(accessibilityData) @@ -1298,7 +1323,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if let (replyInfoSize, replyInfoApply) = replyInfoApply { - let replyInfoNode = replyInfoApply() + let replyInfoNode = replyInfoApply(synchronousLoads) if strongSelf.replyInfoNode == nil { strongSelf.replyInfoNode = replyInfoNode strongSelf.contextSourceNode.contentNode.addSubnode(replyInfoNode) @@ -1685,7 +1710,8 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { .offsetBy(dx: incomingMessage ? animationNode.frame.width - 10.0 : -animationNode.frame.width + 10.0, dy: 0.0) animationFrame = animationFrame.offsetBy(dx: CGFloat.random(in: -30.0 ... 30.0), dy: CGFloat.random(in: -30.0 ... 30.0)) } - + + animationFrame = animationFrame.offsetBy(dx: 0.0, dy: self.insets.top) additionalAnimationNode.frame = animationFrame if incomingMessage { additionalAnimationNode.transform = CATransform3DMakeScale(-1.0, 1.0, 1.0) @@ -1794,7 +1820,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { return .optionalAction({ item.controllerInteraction.displayDiceTooltip(dice) }) - } else if let _ = self.emojiFile { + } else if let emojiFile = self.emojiFile, !emojiFile.isCustomEmoji { if let animationNode = self.animationNode as? AnimatedStickerNode, let _ = recognizer { var shouldPlay = false if !animationNode.isPlaying { @@ -2319,18 +2345,13 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let localSourceContentFrame = CGRect( origin: CGPoint( - x: self.imageNode.frame.minX + self.imageNode.frame.size.width / 2.0 - stickerSource.imageNode.frame.size.width / 2.0, - y: self.imageNode.frame.minY + self.imageNode.frame.size.height / 2.0 - stickerSource.imageNode.frame.size.height / 2.0 + x: self.imageNode.frame.minX + self.imageNode.frame.size.width / 2.0 - stickerSource.sourceFrame.size.width / 2.0, + y: self.imageNode.frame.minY + self.imageNode.frame.size.height / 2.0 - stickerSource.sourceFrame.size.height / 2.0 ), - size: stickerSource.imageNode.frame.size + size: stickerSource.sourceFrame.size ) - var snapshotView: UIView? - if let animationNode = stickerSource.animationNode { - snapshotView = animationNode.view.snapshotContentTree() - } else { - snapshotView = stickerSource.imageNode.view.snapshotContentTree() - } + let snapshotView: UIView? = stickerSource.snapshotContentTree() snapshotView?.frame = localSourceContentFrame if let snapshotView = snapshotView { @@ -2350,7 +2371,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { y: localSourceCenter.y - localSourceContentFrame.height / 2.0 ) - let sourceScale: CGFloat = stickerSource.imageNode.frame.height / self.imageNode.frame.height + let sourceScale: CGFloat = stickerSource.sourceFrame.height / self.imageNode.frame.height let offset = CGPoint( x: sourceCenter.x - self.imageNode.frame.midX, @@ -2393,8 +2414,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { animationNode.layer.animateAlpha(from: 0.0, to: animationNode.alpha, duration: 0.4) } - stickerSource.imageNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) - stickerSource.imageNode.layer.animateAlpha(from: 0.0, to: stickerSource.imageNode.alpha, duration: 0.4) + if let sourceLayer = stickerSource.sourceLayer { + sourceLayer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + sourceLayer.animateAlpha(from: 0.0, to: CGFloat(sourceLayer.opacity), duration: 0.4) + } if let placeholderNode = stickerSource.placeholderNode { placeholderNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) diff --git a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index 77fe6da306..a2ff3fdca7 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift @@ -15,6 +15,9 @@ import PhotoResources import WebsiteType import ChatMessageInteractiveMediaBadge import GalleryData +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer private let buttonFont = Font.semibold(13.0) @@ -217,7 +220,7 @@ final class ChatMessageAttachedContentButtonNode: HighlightTrackingButtonNode { final class ChatMessageAttachedContentNode: ASDisplayNode { private let lineNode: ASImageNode - private let textNode: TextNode + private let textNode: TextNodeWithEntities private let inlineImageNode: TransformImageNode private var contentImageNode: ChatMessageInteractiveMediaNode? private var contentInstantVideoNode: ChatMessageInteractiveInstantVideoNode? @@ -239,8 +242,20 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { var visibility: ListViewItemNodeVisibility = .none { didSet { - self.contentImageNode?.visibility = self.visibility != .none - self.contentInstantVideoNode?.visibility = self.visibility != .none + if oldValue != self.visibility { + self.contentImageNode?.visibility = self.visibility != .none + self.contentInstantVideoNode?.visibility = self.visibility != .none + + switch self.visibility { + case .none: + self.textNode.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + self.textNode.visibilityRect = subRect + } + } } } @@ -250,11 +265,11 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { self.lineNode.displaysAsynchronously = false self.lineNode.displayWithoutProcessing = true - self.textNode = TextNode() - self.textNode.isUserInteractionEnabled = false - self.textNode.displaysAsynchronously = false - self.textNode.contentsScale = UIScreenScale - self.textNode.contentMode = .topLeft + self.textNode = TextNodeWithEntities() + self.textNode.textNode.isUserInteractionEnabled = false + self.textNode.textNode.displaysAsynchronously = false + self.textNode.textNode.contentsScale = UIScreenScale + self.textNode.textNode.contentMode = .topLeft self.inlineImageNode = TransformImageNode() self.inlineImageNode.contentAnimations = [.subsequentUpdates] @@ -266,13 +281,13 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { super.init() self.addSubnode(self.lineNode) - self.addSubnode(self.textNode) + self.addSubnode(self.textNode.textNode) self.addSubnode(self.statusNode) } - func asyncLayout() -> (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { - let textAsyncLayout = TextNode.asyncLayout(self.textNode) + func asyncLayout() -> (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { + let textAsyncLayout = TextNodeWithEntities.asyncLayout(self.textNode) let currentImage = self.media as? TelegramMediaImage let imageLayout = self.inlineImageNode.asyncLayout() let statusLayout = self.statusNode.asyncLayout() @@ -284,7 +299,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { let currentAdditionalImageBadgeNode = self.additionalImageBadgeNode - return { presentationData, automaticDownloadSettings, associatedData, attributes, context, controllerInteraction, message, messageRead, chatLocation, title, subtitle, text, entities, mediaAndFlags, mediaBadge, actionIcon, actionTitle, displayLine, layoutConstants, preparePosition, constrainedSize in + return { presentationData, automaticDownloadSettings, associatedData, attributes, context, controllerInteraction, message, messageRead, chatLocation, title, subtitle, text, entities, mediaAndFlags, mediaBadge, actionIcon, actionTitle, displayLine, layoutConstants, preparePosition, constrainedSize, animationCache, animationRenderer in let isPreview = presentationData.isPreview let fontSize: CGFloat if message.adAttribute != nil { @@ -393,7 +408,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { string.append(NSAttributedString(string: "\n", font: textFont, textColor: messageTheme.primaryTextColor)) } if let entities = entities { - string.append(stringWithAppliedEntities(text, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textBlockQuoteFont)) + string.append(stringWithAppliedEntities(text, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textBlockQuoteFont, message: nil)) } else { string.append(NSAttributedString(string: text + "\n", font: textFont, textColor: messageTheme.primaryTextColor)) } @@ -847,9 +862,24 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { animation.animator.updateFrame(layer: strongSelf.lineNode.layer, frame: CGRect(origin: CGPoint(x: 13.0, y: insets.top), size: CGSize(width: 2.0, height: adjustedLineHeight - insets.top - insets.bottom - 2.0)), completion: nil) strongSelf.lineNode.isHidden = !displayLine - strongSelf.textNode.displaysAsynchronously = !isPreview + strongSelf.textNode.textNode.displaysAsynchronously = !isPreview - let _ = textApply() + let _ = textApply(TextNodeWithEntities.Arguments( + context: context, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: messageTheme.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads + )) + switch strongSelf.visibility { + case .none: + strongSelf.textNode.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + strongSelf.textNode.visibilityRect = subRect + } if let imageFrame = imageFrame { if let updateImageSignal = updateInlineImageSignal { @@ -976,9 +1006,9 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { textVerticalOffset = contentMediaHeight + 7.0 } - strongSelf.textNode.frame = textFrame.offsetBy(dx: 0.0, dy: textVerticalOffset) + strongSelf.textNode.textNode.frame = textFrame.offsetBy(dx: 0.0, dy: textVerticalOffset) if let statusSizeAndApply = statusSizeAndApply { - var statusFrame = CGRect(origin: CGPoint(x: strongSelf.textNode.frame.minX, y: strongSelf.textNode.frame.maxY), size: statusSizeAndApply.0) + var statusFrame = CGRect(origin: CGPoint(x: strongSelf.textNode.textNode.frame.minX, y: strongSelf.textNode.textNode.frame.maxY), size: statusSizeAndApply.0) if let imageFrame = imageFrame { if statusFrame.maxY < imageFrame.maxY + 10.0 { statusFrame.origin.y = max(statusFrame.minY, imageFrame.maxY + 2.0) @@ -1067,11 +1097,11 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction { - let textNodeFrame = self.textNode.frame - if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + let textNodeFrame = self.textNode.textNode.frame + if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { var concealed = true - if let (attributeText, fullText) = self.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { + if let (attributeText, fullText) = self.textNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText) } return .url(url: url, concealed: concealed) @@ -1095,8 +1125,8 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { if let context = self.context, let message = self.message, let theme = self.theme { var rects: [CGRect]? if let point = point { - let textNodeFrame = self.textNode.frame - if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + let textNodeFrame = self.textNode.textNode.frame + if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { let possibleNames: [String] = [ TelegramTextAttributes.URL, TelegramTextAttributes.PeerMention, @@ -1107,7 +1137,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { ] for name in possibleNames { if let _ = attributes[NSAttributedString.Key(rawValue: name)] { - rects = self.textNode.attributeRects(name: name, at: index) + rects = self.textNode.textNode.attributeRects(name: name, at: index) break } } @@ -1121,9 +1151,9 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } else { linkHighlightingNode = LinkHighlightingNode(color: message.effectivelyIncoming(context.account.peerId) ? theme.theme.chat.message.incoming.linkHighlightColor : theme.theme.chat.message.outgoing.linkHighlightColor) self.linkHighlightingNode = linkHighlightingNode - self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode) + self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode.textNode) } - linkHighlightingNode.frame = self.textNode.frame + linkHighlightingNode.frame = self.textNode.textNode.frame linkHighlightingNode.updateRects(rects) } else if let linkHighlightingNode = self.linkHighlightingNode { self.linkHighlightingNode = nil diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 51c7c8505f..7f7efef8c2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -99,6 +99,8 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([ isAction = true if case .phoneCall = action.action { result.append((message, ChatMessageCallBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default))) + } else if case .giftPremium = action.action { + result.append((message, ChatMessageGiftBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default))) } else { result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform, neighborSpacing: .default))) } @@ -299,7 +301,15 @@ class ChatPresentationContext { self.animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { return TempBox.shared.tempFile(fileName: "file").path }) - self.animationRenderer = MultiAnimationRendererImpl() + + let animationRenderer: MultiAnimationRenderer + /*if #available(iOS 13.0, *) { + animationRenderer = MultiAnimationMetalRendererImpl() + } else {*/ + animationRenderer = MultiAnimationRendererImpl() + //} + + self.animationRenderer = animationRenderer } } @@ -528,13 +538,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode contentNode.visibility = mapVisibility(self.visibility, boundsSize: self.bounds.size, insets: self.insets, to: contentNode) } - /*switch self.visibility { - case let .visible(_, subRect): - let topEdge = self.bounds.height - self.insets.top - (subRect.origin.y + subRect.height) - self.debugNode.frame = CGRect(origin: CGPoint(x: 0.0, y: topEdge), size: CGSize(width: 100.0, height: 2.0)) - case .none: - break - }*/ + if let replyInfoNode = self.replyInfoNode { + replyInfoNode.visibility = self.visibility != .none + } } } } @@ -1037,7 +1043,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode authorNameLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode), adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode), forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode), - replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode), + replyInfoLayout: (ChatMessageReplyInfoNode.Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode), actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode)), reactionButtonsLayout: (ChatMessageReactionButtonsNode.Arguments) -> (minWidth: CGFloat, layout: (CGFloat) -> (size: CGSize, apply: (ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode)), mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)), @@ -1693,7 +1699,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode var adminNodeSizeApply: (CGSize, () -> TextNode?) = (CGSize(), { nil }) var replyInfoOriginY: CGFloat = 0.0 - var replyInfoSizeApply: (CGSize, () -> ChatMessageReplyInfoNode?) = (CGSize(), { nil }) + var replyInfoSizeApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode?) = (CGSize(), { _ in nil }) var forwardInfoOriginY: CGFloat = 0.0 var forwardInfoSizeApply: (CGSize, (CGFloat) -> ChatMessageForwardInfoNode?) = (CGSize(), { _ in nil }) @@ -1800,8 +1806,18 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } else { headerSize.height += 2.0 } - let sizeAndApply = replyInfoLayout(item.presentationData, item.presentationData.strings, item.context, .bubble(incoming: incoming), replyMessage, item.message, CGSize(width: maximumNodeWidth - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right, height: CGFloat.greatestFiniteMagnitude)) - replyInfoSizeApply = (sizeAndApply.0, { sizeAndApply.1() }) + let sizeAndApply = replyInfoLayout(ChatMessageReplyInfoNode.Arguments( + presentationData: item.presentationData, + strings: item.presentationData.strings, + context: item.context, + type: .bubble(incoming: incoming), + message: replyMessage, + parentMessage: item.message, + constrainedSize: CGSize(width: maximumNodeWidth - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right, height: CGFloat.greatestFiniteMagnitude), + animationCache: item.controllerInteraction.presentationContext.animationCache, + animationRenderer: item.controllerInteraction.presentationContext.animationRenderer + )) + replyInfoSizeApply = (sizeAndApply.0, { synchronousLoads in sizeAndApply.1(synchronousLoads) }) replyInfoOriginY = headerSize.height headerSize.width = max(headerSize.width, replyInfoSizeApply.0.width + layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right) @@ -2275,7 +2291,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode contentUpperRightCorner: CGPoint, forwardInfoSizeApply: (CGSize, (CGFloat) -> ChatMessageForwardInfoNode?), forwardInfoOriginY: CGFloat, - replyInfoSizeApply: (CGSize, () -> ChatMessageReplyInfoNode?), + replyInfoSizeApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode?), replyInfoOriginY: CGFloat, removedContentNodeIndices: [Int]?, addedContentNodes: [(Message, Bool, ChatMessageBubbleContentNode)]?, @@ -2481,12 +2497,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } } - if let replyInfoNode = replyInfoSizeApply.1() { + if let replyInfoNode = replyInfoSizeApply.1(synchronousLoads) { strongSelf.replyInfoNode = replyInfoNode var animateFrame = true if replyInfoNode.supernode == nil { strongSelf.clippingNode.addSubnode(replyInfoNode) animateFrame = false + + replyInfoNode.visibility = strongSelf.visibility != .none } let previousReplyInfoNodeFrame = replyInfoNode.frame replyInfoNode.frame = CGRect(origin: CGPoint(x: contentOrigin.x + layoutConstants.text.bubbleInsets.left, y: layoutConstants.bubble.contentInsets.top + replyInfoOriginY), size: replyInfoSizeApply.0) diff --git a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift index 52b374d55e..790a8655da 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift @@ -395,6 +395,7 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode { private let containerNode: ContextControllerSourceNode private let avatarNode: AvatarNode private var videoNode: UniversalVideoNode? + private var credibilityIconNode: ASImageNode? private var videoContent: NativeVideoContent? private let playbackStartDisposable = MetaDisposable() @@ -519,7 +520,22 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode { let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start() } })) + + let credibilityIconNode: ASImageNode + if let current = self.credibilityIconNode { + credibilityIconNode = current + } else { + credibilityIconNode = ASImageNode() + credibilityIconNode.displaysAsynchronously = false + credibilityIconNode.displayWithoutProcessing = true + credibilityIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) + self.containerNode.addSubnode(credibilityIconNode) + } + credibilityIconNode.frame = CGRect(origin: CGPoint(x: 29.0 - UIScreenPixel, y: 29.0 - UIScreenPixel), size: CGSize(width: 10.0, height: 10.0)) } else { + self.credibilityIconNode?.removeFromSupernode() + self.credibilityIconNode = nil + self.cachedDataDisposable.set(nil) self.videoContent = nil diff --git a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift index 5d52b3fc0b..9f4ef55e34 100644 --- a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousDescriptionContentNode.swift @@ -9,6 +9,12 @@ import TelegramCore final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubbleContentNode { private let contentNode: ChatMessageAttachedContentNode + override var visibility: ListViewItemNodeVisibility { + didSet { + self.contentNode.visibility = visibility + } + } + required init() { self.contentNode = ChatMessageAttachedContentNode() @@ -43,7 +49,7 @@ final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubble } let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousLinkContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousLinkContentNode.swift index 1118997e9c..facb0a018e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousLinkContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousLinkContentNode.swift @@ -9,6 +9,12 @@ import TelegramCore final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContentNode { private let contentNode: ChatMessageAttachedContentNode + override var visibility: ListViewItemNodeVisibility { + didSet { + self.contentNode.visibility = visibility + } + } + required init() { self.contentNode = ChatMessageAttachedContentNode() @@ -38,7 +44,7 @@ final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContent let text: String = item.message.text let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousMessageContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousMessageContentNode.swift index cbfb47a4ff..364766ccbe 100644 --- a/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousMessageContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageEventLogPreviousMessageContentNode.swift @@ -9,6 +9,12 @@ import TelegramCore final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleContentNode { private let contentNode: ChatMessageAttachedContentNode + override var visibility: ListViewItemNodeVisibility { + didSet { + self.contentNode.visibility = visibility + } + } + required init() { self.contentNode = ChatMessageAttachedContentNode() @@ -43,7 +49,7 @@ final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleCont } let mediaAndFlags: (Media, ChatMessageAttachedContentNodeMediaFlags)? = nil - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, true, .peer(id: item.message.id.peerId), title, nil, text, messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift index b9630d689f..35f51b625f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift @@ -13,7 +13,7 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode { override var visibility: ListViewItemNodeVisibility { didSet { - self.contentNode.visibility = self.visibility + self.contentNode.visibility = visibility } } @@ -77,7 +77,7 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode { } } - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, .peer(id: item.message.id.peerId), title, nil, item.message.text.isEmpty ? text : item.message.text, item.message.text.isEmpty ? nil : messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, .peer(id: item.message.id.peerId), title, nil, item.message.text.isEmpty ? text : item.message.text, item.message.text.isEmpty ? nil : messageEntities, mediaAndFlags, nil, nil, nil, true, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift new file mode 100644 index 0000000000..f0287d959b --- /dev/null +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -0,0 +1,453 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import SwiftSignalKit +import Postbox +import TelegramCore +import AccountContext +import TelegramPresentationData +import TelegramUIPreferences +import TextFormat +import LocalizedPeerData +import UrlEscaping +import TelegramStringFormatting +import WallpaperBackgroundNode +import ReactionSelectionNode +import AnimatedStickerNode +import TelegramAnimatedStickerNode + +private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId) -> NSAttributedString? { + return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false) +} + +class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { + private let labelNode: TextNode + private var backgroundNode: WallpaperBubbleBackgroundNode? + private var backgroundColorNode: ASDisplayNode + private let backgroundMaskNode: ASImageNode + private var linkHighlightingNode: LinkHighlightingNode? + + private let mediaBackgroundNode: NavigationBackgroundNode + private let titleNode: TextNode + private let subtitleNode: TextNode + private let animationNode: AnimatedStickerNode + + private let buttonNode: HighlightTrackingButtonNode + private let buttonStarsNode: PremiumStarsNode + private let buttonTitleNode: TextNode + + private var cachedMaskBackgroundImage: (CGPoint, UIImage, [CGRect])? + private var absoluteRect: (CGRect, CGSize)? + + private var isPlaying: Bool = false + + override var visibility: ListViewItemNodeVisibility { + didSet { + let wasVisible = oldValue != .none + let isVisible = self.visibility != .none + + if wasVisible != isVisible { + self.visibilityStatus = isVisible + } + } + } + + private var visibilityStatus: Bool? { + didSet { + if self.visibilityStatus != oldValue { + self.updateVisibility() + } + } + } + + required init() { + self.labelNode = TextNode() + self.labelNode.isUserInteractionEnabled = false + self.labelNode.displaysAsynchronously = false + + self.backgroundColorNode = ASDisplayNode() + self.backgroundMaskNode = ASImageNode() + + self.mediaBackgroundNode = NavigationBackgroundNode(color: .clear) + self.mediaBackgroundNode.clipsToBounds = true + self.mediaBackgroundNode.cornerRadius = 24.0 + + self.titleNode = TextNode() + self.titleNode.isUserInteractionEnabled = false + self.titleNode.displaysAsynchronously = false + + self.subtitleNode = TextNode() + self.subtitleNode.isUserInteractionEnabled = false + self.subtitleNode.displaysAsynchronously = false + + self.buttonNode = HighlightTrackingButtonNode() + self.buttonNode.clipsToBounds = true + self.buttonNode.cornerRadius = 17.0 + + self.animationNode = DefaultAnimatedStickerNodeImpl() + + self.buttonStarsNode = PremiumStarsNode() + + self.buttonTitleNode = TextNode() + self.buttonTitleNode.isUserInteractionEnabled = false + self.buttonTitleNode.displaysAsynchronously = false + + super.init() + + self.addSubnode(self.labelNode) + + self.addSubnode(self.mediaBackgroundNode) + self.addSubnode(self.titleNode) + self.addSubnode(self.subtitleNode) + self.addSubnode(self.animationNode) + + self.addSubnode(self.buttonNode) + self.buttonNode.addSubnode(self.buttonStarsNode) + self.addSubnode(self.buttonTitleNode) + + self.buttonNode.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.buttonNode.layer.removeAnimation(forKey: "opacity") + strongSelf.buttonNode.alpha = 0.4 + strongSelf.buttonTitleNode.layer.removeAnimation(forKey: "opacity") + strongSelf.buttonTitleNode.alpha = 0.4 + } else { + strongSelf.buttonNode.alpha = 1.0 + strongSelf.buttonNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + strongSelf.buttonTitleNode.alpha = 1.0 + strongSelf.buttonTitleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + + self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func buttonPressed() { + guard let item = self.item else { + return + } + let _ = item.controllerInteraction.openMessage(item.message, .default) + } + + override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { + let makeLabelLayout = TextNode.asyncLayout(self.labelNode) + let makeTitleLayout = TextNode.asyncLayout(self.titleNode) + let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode) + let makeButtonTitleLayout = TextNode.asyncLayout(self.buttonTitleNode) + + let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage + + return { item, layoutConstants, _, _, _ in + let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center) + + return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in + let giftSize = CGSize(width: 220.0, height: 240.0) + + let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: item.message, accountPeerId: item.context.account.peerId) + + let primaryTextColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText + + var duration: String = "" + var animationName: String = "" + for media in item.message.media { + if let action = media as? TelegramMediaAction { + switch action.action { + case let .giftPremium(_, _, months): + duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(months)).string + switch months { + case 12: + animationName = "Gift12" + case 6: + animationName = "Gift6" + case 3: + animationName = "Gift3" + default: + animationName = "Gift3" + } + default: + break + } + } + } + + let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: attributedString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: constrainedSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Notification_PremiumGift_Title, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: duration, font: Font.regular(13.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.presentationData.strings.Notification_PremiumGift_View, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + var labelRects = labelLayout.linesRects() + if labelRects.count > 1 { + let sortedIndices = (0 ..< labelRects.count).sorted(by: { labelRects[$0].width > labelRects[$1].width }) + for i in 0 ..< sortedIndices.count { + let index = sortedIndices[i] + for j in -1 ... 1 { + if j != 0 && index + j >= 0 && index + j < sortedIndices.count { + if abs(labelRects[index + j].width - labelRects[index].width) < 40.0 { + labelRects[index + j].size.width = max(labelRects[index + j].width, labelRects[index].width) + labelRects[index].size.width = labelRects[index + j].size.width + } + } + } + } + } + for i in 0 ..< labelRects.count { + labelRects[i] = labelRects[i].insetBy(dx: -6.0, dy: floor((labelRects[i].height - 20.0) / 2.0)) + labelRects[i].size.height = 20.0 + labelRects[i].origin.x = floor((labelLayout.size.width - labelRects[i].width) / 2.0) + } + + let backgroundMaskImage: (CGPoint, UIImage)? + var backgroundMaskUpdated = false + if let (currentOffset, currentImage, currentRects) = cachedMaskBackgroundImage, currentRects == labelRects { + backgroundMaskImage = (currentOffset, currentImage) + } else { + backgroundMaskImage = LinkHighlightingNode.generateImage(color: .black, inset: 0.0, innerRadius: 10.0, outerRadius: 10.0, rects: labelRects) + backgroundMaskUpdated = true + } + + let backgroundSize = CGSize(width: labelLayout.size.width + 8.0 + 8.0, height: labelLayout.size.height + giftSize.height + 18.0) + + return (backgroundSize.width, { boundingWidth in + return (backgroundSize, { [weak self] animation, synchronousLoads, _ in + if let strongSelf = self { + if strongSelf.item == nil { + strongSelf.animationNode.autoplay = true + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 384, height: 384, playbackMode: .still(.end), mode: .direct(cachePathPrefix: nil)) + } + strongSelf.item = item + + strongSelf.updateVisibility() + + strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + + let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - giftSize.width) / 2.0), y: labelLayout.size.height + 16.0), size: giftSize) + let mediaBackgroundFrame = imageFrame.insetBy(dx: -2.0, dy: -2.0) + strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame + + strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate) + strongSelf.mediaBackgroundNode.update(size: mediaBackgroundFrame.size, transition: .immediate) + strongSelf.buttonNode.backgroundColor = item.presentationData.theme.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12) + + let iconSize = CGSize(width: 160.0, height: 160.0) + strongSelf.animationNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - iconSize.width) / 2.0), y: mediaBackgroundFrame.minY - 16.0), size: iconSize) + strongSelf.animationNode.updateLayout(size: iconSize) + + let _ = labelApply() + let _ = titleApply() + let _ = subtitleApply() + let _ = buttonTitleApply() + + let labelFrame = CGRect(origin: CGPoint(x: 8.0, y: 2.0), size: labelLayout.size) + strongSelf.labelNode.frame = labelFrame + + let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size) + strongSelf.titleNode.frame = titleFrame + + let subtitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: titleFrame.maxY - 1.0), size: subtitleLayout.size) + strongSelf.subtitleNode.frame = subtitleFrame + + let buttonTitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonTitleLayout.size.width) / 2.0), y: subtitleFrame.maxY + 18.0), size: buttonTitleLayout.size) + strongSelf.buttonTitleNode.frame = buttonTitleFrame + + let buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0) + strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: subtitleFrame.maxY + 10.0), size: buttonSize) + strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize) + + let baseBackgroundFrame = labelFrame.offsetBy(dx: 0.0, dy: -11.0) + if let (offset, image) = backgroundMaskImage { + if strongSelf.backgroundNode == nil { + if let backgroundNode = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + strongSelf.backgroundNode = backgroundNode + backgroundNode.addSubnode(strongSelf.backgroundColorNode) + strongSelf.insertSubnode(backgroundNode, at: 0) + } + } + + if backgroundMaskUpdated, let backgroundNode = strongSelf.backgroundNode { + if labelRects.count == 1 { + backgroundNode.clipsToBounds = true + backgroundNode.cornerRadius = labelRects[0].height / 2.0 + backgroundNode.view.mask = nil + } else { + backgroundNode.clipsToBounds = false + backgroundNode.cornerRadius = 0.0 + backgroundNode.view.mask = strongSelf.backgroundMaskNode.view + } + } + + if let backgroundNode = strongSelf.backgroundNode { + backgroundNode.frame = CGRect(origin: CGPoint(x: baseBackgroundFrame.minX + offset.x, y: baseBackgroundFrame.minY + offset.y), size: image.size) + if let (rect, size) = strongSelf.absoluteRect { + strongSelf.updateAbsoluteRect(rect, within: size) + } + } + strongSelf.backgroundMaskNode.image = image + strongSelf.backgroundMaskNode.frame = CGRect(origin: CGPoint(), size: image.size) + strongSelf.backgroundColorNode.frame = CGRect(origin: CGPoint(), size: image.size) + + strongSelf.cachedMaskBackgroundImage = (offset, image, labelRects) + } + } + }) + }) + }) + } + } + + override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { + self.absoluteRect = (rect, containerSize) + + if let backgroundNode = self.backgroundNode { + var backgroundFrame = backgroundNode.frame + backgroundFrame.origin.x += rect.minX + backgroundFrame.origin.y += rect.minY + backgroundNode.update(rect: backgroundFrame, within: containerSize, transition: .immediate) + } + } + + override func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + if let backgroundNode = self.backgroundNode { + backgroundNode.offset(value: value, animationCurve: animationCurve, duration: duration) + } + } + + override func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) { + if let backgroundNode = self.backgroundNode { + backgroundNode.offsetSpring(value: value, duration: duration, damping: damping) + } + } + + override func updateTouchesAtPoint(_ point: CGPoint?) { + if let item = self.item { + var rects: [(CGRect, CGRect)]? + let textNodeFrame = self.labelNode.frame + if let point = point { + if let (index, attributes) = self.labelNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)) { + let possibleNames: [String] = [ + TelegramTextAttributes.URL, + TelegramTextAttributes.PeerMention, + TelegramTextAttributes.PeerTextMention, + TelegramTextAttributes.BotCommand, + TelegramTextAttributes.Hashtag + ] + for name in possibleNames { + if let _ = attributes[NSAttributedString.Key(rawValue: name)] { + rects = self.labelNode.lineAndAttributeRects(name: name, at: index) + break + } + } + } + } + + if let rects = rects { + var mappedRects: [CGRect] = [] + for i in 0 ..< rects.count { + let lineRect = rects[i].0 + var itemRect = rects[i].1 + itemRect.origin.x = floor((textNodeFrame.size.width - lineRect.width) / 2.0) + itemRect.origin.x + mappedRects.append(itemRect) + } + + let linkHighlightingNode: LinkHighlightingNode + if let current = self.linkHighlightingNode { + linkHighlightingNode = current + } else { + let serviceColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + linkHighlightingNode = LinkHighlightingNode(color: serviceColor.linkHighlight) + linkHighlightingNode.inset = 2.5 + self.linkHighlightingNode = linkHighlightingNode + self.insertSubnode(linkHighlightingNode, belowSubnode: self.labelNode) + } + linkHighlightingNode.frame = self.labelNode.frame.offsetBy(dx: 0.0, dy: 1.5) + linkHighlightingNode.updateRects(mappedRects) + } else if let linkHighlightingNode = self.linkHighlightingNode { + self.linkHighlightingNode = nil + linkHighlightingNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak linkHighlightingNode] _ in + linkHighlightingNode?.removeFromSupernode() + }) + } + } + } + + override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction { + let textNodeFrame = self.labelNode.frame + if let (index, attributes) = self.labelNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY - 10.0)), gesture == .tap { + if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { + var concealed = true + if let (attributeText, fullText) = self.labelNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { + concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText) + } + return .url(url: url, concealed: concealed) + } else if let peerMention = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerMention)] as? TelegramPeerMention { + return .peerMention(peerMention.peerId, peerMention.mention) + } else if let peerName = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention)] as? String { + return .textMention(peerName) + } else if let botCommand = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.BotCommand)] as? String { + return .botCommand(botCommand) + } else if let hashtag = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag)] as? TelegramHashtag { + return .hashtag(hashtag.peerName, hashtag.hashtag) + } + } + + if let backgroundNode = self.backgroundNode, backgroundNode.frame.contains(point) { + return .openMessage + } else if self.mediaBackgroundNode.frame.contains(point) { + return .openMessage + } else { + return .none + } + } + + override func unreadMessageRangeUpdated() { + self.updateVisibility() + } + + private func updateVisibility() { + guard let item = self.item else { + return + } + + let isPlaying = self.visibilityStatus == true + if self.isPlaying != isPlaying { + self.isPlaying = isPlaying + self.animationNode.visibility = isPlaying + } + + if isPlaying { + var alreadySeen = true + + if item.message.flags.contains(.Incoming) { + if let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] { + if unreadRange.contains(item.message.id.id) { + alreadySeen = false + } + } + } else { + if item.controllerInteraction.playNextOutgoingGift && !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) { + alreadySeen = false + } + } + + if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) { + item.controllerInteraction.seenOneTimeAnimatedMedia.insert(item.message.id) + self.animationNode.playOnce() + } + + if !alreadySeen { + Queue.mainQueue().after(1.0) { + item.controllerInteraction.animateDiceSuccess(false, true) + } + } + } + } +} diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 6fc9c5eddb..ea5cbd4cf7 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -65,6 +65,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD if wasVisible != isVisible { self.interactiveVideoNode.visibility = isVisible + self.replyInfoNode?.visibility = isVisible } } } @@ -393,7 +394,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD let videoFrame = CGRect(origin: CGPoint(x: (incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + effectiveAvatarInset + layoutConstants.bubble.contentInsets.left) : (params.width - params.rightInset - videoLayout.contentSize.width - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - deliveryFailedInset)), y: 0.0), size: videoLayout.contentSize) var viaBotApply: (TextNodeLayout, () -> TextNode)? - var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? + var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)? var updatedReplyBackgroundNode: NavigationBackgroundNode? var replyMarkup: ReplyMarkupMessageAttribute? @@ -458,7 +459,17 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId { } else { - replyInfoApply = makeReplyInfoLayout(item.presentationData, item.presentationData.strings, item.context, .standalone, replyMessage, item.message, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude)) + replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments( + presentationData: item.presentationData, + strings: item.presentationData.strings, + context: item.context, + type: .standalone, + message: replyMessage, + parentMessage: item.message, + constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude), + animationCache: item.controllerInteraction.presentationContext.animationCache, + animationRenderer: item.controllerInteraction.presentationContext.animationRenderer + )) } } else if let _ = attribute as? InlineBotMessageAttribute { } else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty { @@ -570,7 +581,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD layoutSize.height += 6.0 + reactionButtonsSizeAndApply.0.height } - return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, _ in + return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, synchronousLoads in if let strongSelf = self { strongSelf.contextSourceNode.frame = CGRect(origin: CGPoint(), size: layoutSize) strongSelf.containerNode.frame = CGRect(origin: CGPoint(), size: layoutSize) @@ -696,7 +707,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD } if let (replyInfoSize, replyInfoApply) = replyInfoApply { - let replyInfoNode = replyInfoApply() + let replyInfoNode = replyInfoApply(synchronousLoads) if strongSelf.replyInfoNode == nil { strongSelf.replyInfoNode = replyInfoNode strongSelf.contextSourceNode.contentNode.addSubnode(replyInfoNode) diff --git a/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift index 4f900a526b..2dd754cc31 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift @@ -73,7 +73,7 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode { } } - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, automaticDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, item.chatLocation, title, subtitle, text, nil, mediaAndFlags, nil, nil, nil, false, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, automaticDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, item.chatLocation, title, subtitle, text, nil, mediaAndFlags, nil, nil, nil, false, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatMessageItemView.swift b/submodules/TelegramUI/Sources/ChatMessageItemView.swift index f34d924608..881e1cdecb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItemView.swift +++ b/submodules/TelegramUI/Sources/ChatMessageItemView.swift @@ -206,7 +206,7 @@ final class ChatMessageAccessibilityData { if let chatPeer = message.peers[item.message.id.peerId] { let authorName = message.author.flatMap(EnginePeer.init)?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) - let (_, _, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: [EngineMessage(message)], chatPeer: EngineRenderedPeer(peer: EnginePeer(chatPeer)), accountPeerId: item.context.account.peerId) + let (_, _, messageText, _, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: [EngineMessage(message)], chatPeer: EngineRenderedPeer(peer: EnginePeer(chatPeer)), accountPeerId: item.context.account.peerId) var text = messageText diff --git a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index 23ef6310c4..d6e97e397e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift @@ -15,6 +15,9 @@ import PhotoResources import TelegramStringFormatting import TextFormat import InvisibleInkDustNode +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer public final class ChatMessageNotificationItem: NotificationItem { let context: AccountContext @@ -69,7 +72,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { private let avatarNode: AvatarNode private let titleIconNode: ASImageNode private let titleNode: TextNode - private let textNode: TextNode + private let textNode: TextNodeWithEntities private var dustNode: InvisibleInkDustNode? private let imageNode: TransformImageNode @@ -79,6 +82,9 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { private var compact: Bool? private var validLayout: CGFloat? + private var animationCache: AnimationCache? + private var multiAnimationRenderer: MultiAnimationRenderer? + override init() { self.avatarNode = AvatarNode(font: avatarFont) @@ -90,8 +96,8 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { self.titleIconNode.displayWithoutProcessing = true self.titleIconNode.displaysAsynchronously = false - self.textNode = TextNode() - self.textNode.isUserInteractionEnabled = false + self.textNode = TextNodeWithEntities() + self.textNode.textNode.isUserInteractionEnabled = false self.imageNode = TransformImageNode() @@ -100,12 +106,20 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { self.addSubnode(self.avatarNode) self.addSubnode(self.titleIconNode) self.addSubnode(self.titleNode) - self.addSubnode(self.textNode) + self.addSubnode(self.textNode.textNode) self.addSubnode(self.imageNode) } func setupItem(_ item: ChatMessageNotificationItem, compact: Bool) { self.item = item + + if self.animationCache == nil { + self.animationCache = AnimationCacheImpl(basePath: item.context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + self.multiAnimationRenderer = MultiAnimationRendererImpl() + } + self.compact = compact if compact { self.avatarNode.font = compactAvatarFont @@ -190,16 +204,18 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { messageEntities = message.textEntitiesAttribute?.entities.filter { entity in if case .Spoiler = entity.type { return true + } else if case .CustomEmoji = entity.type { + return true } else { return false } } if messageEntities?.count == 0 { messageEntities = nil - messageText = textString + messageText = textString.string } } else { - messageText = textString + messageText = textString.string } } else if item.messages.count > 1, let peer = item.messages[0].peers[item.messages[0].id.peerId] { var displayAuthor = true @@ -310,7 +326,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { let textColor = presentationData.theme.inAppNotification.primaryTextColor var attributedMessageText: NSAttributedString if let messageEntities = messageEntities { - attributedMessageText = stringWithAppliedEntities(messageText, entities: messageEntities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) + attributedMessageText = stringWithAppliedEntities(messageText, entities: messageEntities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: item.messages.first) } else { attributedMessageText = NSAttributedString(string: messageText.replacingOccurrences(of: "\n\n", with: " "), font: textFont, textColor: textColor) } @@ -384,10 +400,24 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: self.titleAttributedText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - leftInset - rightInset - titleInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) let _ = titleApply() - let makeTextLayout = TextNode.asyncLayout(self.textNode) + let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: self.textAttributedText, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets())) let _ = titleApply() - let _ = textApply() + + if let item = self.item, let cache = self.animationCache, let renderer = self.multiAnimationRenderer { + let theme = item.context.sharedContext.currentPresentationData.with({ $0 }).theme + let _ = textApply(TextNodeWithEntities.Arguments( + context: item.context, + cache: cache, + renderer: renderer, + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false + )) + } else { + let _ = textApply(nil) + } + + self.textNode.visibilityRect = CGRect.infinite let textSpacing: CGFloat = 1.0 @@ -399,7 +429,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { } let textFrame = CGRect(origin: CGPoint(x: leftInset, y: titleFrame.maxY + textSpacing), size: textLayout.size) - transition.updateFrame(node: self.textNode, frame: textFrame) + transition.updateFrame(node: self.textNode.textNode, frame: textFrame) transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: width - 10.0 - imageSize.width, y: (panelHeight - imageSize.height) / 2.0), size: imageSize)) @@ -411,7 +441,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { dustNode = InvisibleInkDustNode(textNode: nil) dustNode.isUserInteractionEnabled = false self.dustNode = dustNode - self.insertSubnode(dustNode, aboveSubnode: self.textNode) + self.insertSubnode(dustNode, aboveSubnode: self.textNode.textNode) } dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0) dustNode.update(size: dustNode.frame.size, color: presentationData.theme.inAppNotification.primaryTextColor, textColor: presentationData.theme.inAppNotification.primaryTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }) diff --git a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift index 0f6935d5ba..ac2d2e9950 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift @@ -12,6 +12,9 @@ import PhotoResources import TelegramStringFormatting import TextFormat import InvisibleInkDustNode +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer enum ChatMessageReplyInfoType { case bubble(incoming: Bool) @@ -19,10 +22,52 @@ enum ChatMessageReplyInfoType { } class ChatMessageReplyInfoNode: ASDisplayNode { + class Arguments { + let presentationData: ChatPresentationData + let strings: PresentationStrings + let context: AccountContext + let type: ChatMessageReplyInfoType + let message: Message + let parentMessage: Message + let constrainedSize: CGSize + let animationCache: AnimationCache? + let animationRenderer: MultiAnimationRenderer? + + init( + presentationData: ChatPresentationData, + strings: PresentationStrings, + context: AccountContext, + type: ChatMessageReplyInfoType, + message: Message, + parentMessage: Message, + constrainedSize: CGSize, + animationCache: AnimationCache?, + animationRenderer: MultiAnimationRenderer? + ) { + self.presentationData = presentationData + self.strings = strings + self.context = context + self.type = type + self.message = message + self.parentMessage = parentMessage + self.constrainedSize = constrainedSize + self.animationCache = animationCache + self.animationRenderer = animationRenderer + } + } + + var visibility: Bool = false { + didSet { + if self.visibility != oldValue { + self.textNode?.visibilityRect = self.visibility ? CGRect.infinite : nil + } + } + } + private let contentNode: ASDisplayNode private let lineNode: ASImageNode private var titleNode: TextNode? - private var textNode: TextNode? + private var textNode: TextNodeWithEntities? private var dustNode: InvisibleInkDustNode? private var imageNode: TransformImageNode? private var previousMediaReference: AnyMediaReference? @@ -45,31 +90,33 @@ class ChatMessageReplyInfoNode: ASDisplayNode { self.contentNode.addSubnode(self.lineNode) } - class func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ theme: ChatPresentationData, _ strings: PresentationStrings, _ context: AccountContext, _ type: ChatMessageReplyInfoType, _ message: Message, _ parentMessage: Message, _ constrainedSize: CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode) { + class func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ arguments: Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode) { let titleNodeLayout = TextNode.asyncLayout(maybeNode?.titleNode) - let textNodeLayout = TextNode.asyncLayout(maybeNode?.textNode) + let textNodeLayout = TextNodeWithEntities.asyncLayout(maybeNode?.textNode) let imageNodeLayout = TransformImageNode.asyncLayout(maybeNode?.imageNode) let previousMediaReference = maybeNode?.previousMediaReference - return { presentationData, strings, context, type, message, parentMessage, constrainedSize in - let fontSize = floor(presentationData.fontSize.baseDisplaySize * 14.0 / 17.0) + return { arguments in + //presentationData, strings, context, type, message, parentMessage, constrainedSize + + let fontSize = floor(arguments.presentationData.fontSize.baseDisplaySize * 14.0 / 17.0) let titleFont = Font.medium(fontSize) let textFont = Font.regular(fontSize) - let author = message.effectiveAuthor - var titleString = author.flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder) ?? strings.User_DeletedAccount + let author = arguments.message.effectiveAuthor + var titleString = author.flatMap(EnginePeer.init)?.displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder) ?? arguments.strings.User_DeletedAccount - if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) || parentMessage.forwardInfo != nil { + if let forwardInfo = arguments.message.forwardInfo, forwardInfo.flags.contains(.isImported) || arguments.parentMessage.forwardInfo != nil { if let author = forwardInfo.author { - titleString = EnginePeer(author).displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder) + titleString = EnginePeer(author).displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder) } else if let authorSignature = forwardInfo.authorSignature { titleString = authorSignature } } - let (textString, isMedia, isText) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: context.account.peerId) + let (textString, isMedia, isText) = descriptionStringForMessage(contentSettings: arguments.context.currentContentSettings.with { $0 }, message: EngineMessage(arguments.message), strings: arguments.strings, nameDisplayOrder: arguments.presentationData.nameDisplayOrder, dateTimeFormat: arguments.presentationData.dateTimeFormat, accountPeerId: arguments.context.account.peerId) - let placeholderColor: UIColor = message.effectivelyIncoming(context.account.peerId) ? presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor + let placeholderColor: UIColor = arguments.message.effectivelyIncoming(arguments.context.account.peerId) ? arguments.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : arguments.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor let titleColor: UIColor let lineImage: UIImage? let textColor: UIColor @@ -77,11 +124,11 @@ class ChatMessageReplyInfoNode: ASDisplayNode { var authorNameColor: UIColor? - if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(parentMessage.id.peerId.namespace) && author?.id.namespace == Namespaces.Peer.CloudUser { + if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(arguments.parentMessage.id.peerId.namespace) && author?.id.namespace == Namespaces.Peer.CloudUser { authorNameColor = author.flatMap { chatMessagePeerIdColors[Int(clamping: $0.id.id._internalGetInt64Value() % 7)] } if let rawAuthorNameColor = authorNameColor { var dimColors = false - switch presentationData.theme.theme.name { + switch arguments.presentationData.theme.theme.name { case .builtin(.nightAccent), .builtin(.night): dimColors = true default: @@ -97,21 +144,21 @@ class ChatMessageReplyInfoNode: ASDisplayNode { } } - switch type { + switch arguments.type { case let .bubble(incoming): - titleColor = incoming ? (authorNameColor ?? presentationData.theme.theme.chat.message.incoming.accentTextColor) : presentationData.theme.theme.chat.message.outgoing.accentTextColor - lineImage = incoming ? (authorNameColor.flatMap({ PresentationResourcesChat.chatBubbleVerticalLineImage(color: $0) }) ?? PresentationResourcesChat.chatBubbleVerticalLineIncomingImage(presentationData.theme.theme)) : PresentationResourcesChat.chatBubbleVerticalLineOutgoingImage(presentationData.theme.theme) + titleColor = incoming ? (authorNameColor ?? arguments.presentationData.theme.theme.chat.message.incoming.accentTextColor) : arguments.presentationData.theme.theme.chat.message.outgoing.accentTextColor + lineImage = incoming ? (authorNameColor.flatMap({ PresentationResourcesChat.chatBubbleVerticalLineImage(color: $0) }) ?? PresentationResourcesChat.chatBubbleVerticalLineIncomingImage(arguments.presentationData.theme.theme)) : PresentationResourcesChat.chatBubbleVerticalLineOutgoingImage(arguments.presentationData.theme.theme) if isMedia { - textColor = incoming ? presentationData.theme.theme.chat.message.incoming.secondaryTextColor : presentationData.theme.theme.chat.message.outgoing.secondaryTextColor + textColor = incoming ? arguments.presentationData.theme.theme.chat.message.incoming.secondaryTextColor : arguments.presentationData.theme.theme.chat.message.outgoing.secondaryTextColor } else { - textColor = incoming ? presentationData.theme.theme.chat.message.incoming.primaryTextColor : presentationData.theme.theme.chat.message.outgoing.primaryTextColor + textColor = incoming ? arguments.presentationData.theme.theme.chat.message.incoming.primaryTextColor : arguments.presentationData.theme.theme.chat.message.outgoing.primaryTextColor } - dustColor = incoming ? presentationData.theme.theme.chat.message.incoming.secondaryTextColor : presentationData.theme.theme.chat.message.outgoing.secondaryTextColor + dustColor = incoming ? arguments.presentationData.theme.theme.chat.message.incoming.secondaryTextColor : arguments.presentationData.theme.theme.chat.message.outgoing.secondaryTextColor case .standalone: - let serviceColor = serviceMessageColorComponents(theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper) + let serviceColor = serviceMessageColorComponents(theme: arguments.presentationData.theme.theme, wallpaper: arguments.presentationData.theme.wallpaper) titleColor = serviceColor.primaryText - let graphics = PresentationResourcesChat.additionalGraphics(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, bubbleCorners: presentationData.chatBubbleCorners) + let graphics = PresentationResourcesChat.additionalGraphics(arguments.presentationData.theme.theme, wallpaper: arguments.presentationData.theme.wallpaper, bubbleCorners: arguments.presentationData.chatBubbleCorners) lineImage = graphics.chatServiceVerticalLineImage textColor = titleColor dustColor = titleColor @@ -120,20 +167,22 @@ class ChatMessageReplyInfoNode: ASDisplayNode { let messageText: NSAttributedString if isText { - let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in + let entities = (arguments.message.textEntitiesAttribute?.entities ?? []).filter { entity in if case .Spoiler = entity.type { return true + } else if case .CustomEmoji = entity.type { + return true } else { return false } } if entities.count > 0 { - messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) + messageText = stringWithAppliedEntities(trimToLineCount(arguments.message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: arguments.message) } else { - messageText = NSAttributedString(string: textString, font: textFont, textColor: textColor) + messageText = NSAttributedString(string: textString.string, font: textFont, textColor: textColor) } } else { - messageText = NSAttributedString(string: textString, font: textFont, textColor: textColor) + messageText = NSAttributedString(string: textString.string, font: textFont, textColor: textColor) } var leftInset: CGFloat = 11.0 @@ -142,16 +191,16 @@ class ChatMessageReplyInfoNode: ASDisplayNode { var updatedMediaReference: AnyMediaReference? var imageDimensions: CGSize? var hasRoundImage = false - if !message.containsSecretMedia { - for media in message.media { + if !arguments.message.containsSecretMedia { + for media in arguments.message.media { if let image = media as? TelegramMediaImage { - updatedMediaReference = .message(message: MessageReference(message), media: image) + updatedMediaReference = .message(message: MessageReference(arguments.message), media: image) if let representation = largestRepresentationForPhoto(image) { imageDimensions = representation.dimensions.cgSize } break } else if let file = media as? TelegramMediaFile, file.isVideo && !file.isVideoSticker { - updatedMediaReference = .message(message: MessageReference(message), media: file) + updatedMediaReference = .message(message: MessageReference(arguments.message), media: file) if let dimensions = file.dimensions { imageDimensions = dimensions.cgSize @@ -168,12 +217,12 @@ class ChatMessageReplyInfoNode: ASDisplayNode { var imageTextInset: CGFloat = 0.0 if let _ = imageDimensions { - imageTextInset += floor(presentationData.fontSize.baseDisplaySize * 32.0 / 17.0) + imageTextInset += floor(arguments.presentationData.fontSize.baseDisplaySize * 32.0 / 17.0) } - let maximumTextWidth = max(0.0, constrainedSize.width - imageTextInset) + let maximumTextWidth = max(0.0, arguments.constrainedSize.width - imageTextInset) - let contrainedTextSize = CGSize(width: maximumTextWidth, height: constrainedSize.height) + let contrainedTextSize = CGSize(width: maximumTextWidth, height: arguments.constrainedSize.height) let textInsets = UIEdgeInsets(top: 3.0, left: 0.0, bottom: 3.0, right: 0.0) @@ -206,19 +255,19 @@ class ChatMessageReplyInfoNode: ASDisplayNode { var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? if let updatedMediaReference = updatedMediaReference, mediaUpdated && imageDimensions != nil { if let imageReference = updatedMediaReference.concrete(TelegramMediaImage.self) { - updateImageSignal = chatMessagePhotoThumbnail(account: context.account, photoReference: imageReference) + updateImageSignal = chatMessagePhotoThumbnail(account: arguments.context.account, photoReference: imageReference) } else if let fileReference = updatedMediaReference.concrete(TelegramMediaFile.self) { if fileReference.media.isVideo { - updateImageSignal = chatMessageVideoThumbnail(account: context.account, fileReference: fileReference) + updateImageSignal = chatMessageVideoThumbnail(account: arguments.context.account, fileReference: fileReference) } else if let iconImageRepresentation = smallestImageRepresentation(fileReference.media.previewRepresentations) { - updateImageSignal = chatWebpageSnippetFile(account: context.account, mediaReference: fileReference.abstract, representation: iconImageRepresentation) + updateImageSignal = chatWebpageSnippetFile(account: arguments.context.account, mediaReference: fileReference.abstract, representation: iconImageRepresentation) } } } let size = CGSize(width: max(titleLayout.size.width - textInsets.left - textInsets.right, textLayout.size.width - textInsets.left - textInsets.right) + leftInset, height: titleLayout.size.height + textLayout.size.height - 2 * (textInsets.top + textInsets.bottom) + 2 * spacing) - return (size, { + return (size, { attemptSynchronous in let node: ChatMessageReplyInfoNode if let maybeNode = maybeNode { node = maybeNode @@ -228,11 +277,16 @@ class ChatMessageReplyInfoNode: ASDisplayNode { node.previousMediaReference = updatedMediaReference - node.titleNode?.displaysAsynchronously = !presentationData.isPreview - node.textNode?.displaysAsynchronously = !presentationData.isPreview + node.titleNode?.displaysAsynchronously = !arguments.presentationData.isPreview + node.textNode?.textNode.displaysAsynchronously = !arguments.presentationData.isPreview let titleNode = titleApply() - let textNode = textApply() + var textArguments: TextNodeWithEntities.Arguments? + if let cache = arguments.animationCache, let renderer = arguments.animationRenderer { + textArguments = TextNodeWithEntities.Arguments(context: arguments.context, cache: cache, renderer: renderer, placeholderColor: placeholderColor, attemptSynchronous: attemptSynchronous) + } + let textNode = textApply(textArguments) + textNode.visibilityRect = node.visibility ? CGRect.infinite : nil if node.titleNode == nil { titleNode.isUserInteractionEnabled = false @@ -241,9 +295,9 @@ class ChatMessageReplyInfoNode: ASDisplayNode { } if node.textNode == nil { - textNode.isUserInteractionEnabled = false + textNode.textNode.isUserInteractionEnabled = false node.textNode = textNode - node.contentNode.addSubnode(textNode) + node.contentNode.addSubnode(textNode.textNode) } if let applyImage = applyImage { @@ -262,12 +316,12 @@ class ChatMessageReplyInfoNode: ASDisplayNode { imageNode.removeFromSupernode() node.imageNode = nil } - node.imageNode?.captureProtected = message.isCopyProtected() + node.imageNode?.captureProtected = arguments.message.isCopyProtected() titleNode.frame = CGRect(origin: CGPoint(x: leftInset - textInsets.left - 2.0, y: spacing - textInsets.top + 1.0), size: titleLayout.size) let textFrame = CGRect(origin: CGPoint(x: leftInset - textInsets.left - 2.0, y: titleNode.frame.maxY - textInsets.bottom + spacing - textInsets.top - 2.0), size: textLayout.size) - textNode.frame = textFrame + textNode.textNode.frame = textFrame if !textLayout.spoilers.isEmpty { let dustNode: InvisibleInkDustNode @@ -277,7 +331,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { dustNode = InvisibleInkDustNode(textNode: nil) dustNode.isUserInteractionEnabled = false node.dustNode = dustNode - node.contentNode.insertSubnode(dustNode, aboveSubnode: textNode) + node.contentNode.insertSubnode(dustNode, aboveSubnode: textNode.textNode) } dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0) dustNode.update(size: dustNode.frame.size, color: dustColor, textColor: dustColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }) @@ -344,16 +398,16 @@ class ChatMessageReplyInfoNode: ASDisplayNode { if let textNode = self.textNode { let offset = CGPoint( - x: localRect.minX + sourceReplyPanel.textNode.frame.minX - textNode.frame.minX, - y: localRect.minY + sourceReplyPanel.textNode.frame.midY - textNode.frame.midY + x: localRect.minX + sourceReplyPanel.textNode.frame.minX - textNode.textNode.frame.minX, + y: localRect.minY + sourceReplyPanel.textNode.frame.midY - textNode.textNode.frame.midY ) - transition.horizontal.animatePositionAdditive(node: textNode, offset: CGPoint(x: offset.x, y: 0.0)) - transition.vertical.animatePositionAdditive(node: textNode, offset: CGPoint(x: 0.0, y: offset.y)) + transition.horizontal.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: offset.x, y: 0.0)) + transition.vertical.animatePositionAdditive(node: textNode.textNode, offset: CGPoint(x: 0.0, y: offset.y)) sourceParentNode.addSubnode(sourceReplyPanel.textNode) - textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) + textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1) sourceReplyPanel.textNode.frame = sourceReplyPanel.textNode.frame .offsetBy(dx: sourceParentOffset.x, dy: sourceParentOffset.y) diff --git a/submodules/TelegramUI/Sources/ChatMessageReportInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatMessageReportInputPanelNode.swift index 39f695d631..507373f8a2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReportInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReportInputPanelNode.swift @@ -71,7 +71,7 @@ final class ChatMessageReportInputPanelNode: ChatInputPanelNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift index b802d1f7e9..d7a7134c69 100644 --- a/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift @@ -94,7 +94,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode { let textFont = item.presentationData.messageFont - let attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor.withAlphaComponent(0.7), linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont) + let attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor.withAlphaComponent(0.7), linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, message: nil) let textInsets = UIEdgeInsets(top: 2.0, left: 0.0, bottom: 5.0, right: 0.0) diff --git a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift index 754c1371d9..e8c465c9e4 100644 --- a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift @@ -17,7 +17,7 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { private let shareButton: HighlightableButtonNode private let separatorNode: ASDisplayNode - private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool)? + private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool, isMediaInputExpanded: Bool)? private var presentationInterfaceState: ChatPresentationInterfaceState? private var actions: ChatAvailableMessageActions? @@ -33,8 +33,8 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { if self.selectedMessages.isEmpty { self.actions = nil - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) = self.validLayout, let interfaceState = self.presentationInterfaceState { - let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout, let interfaceState = self.presentationInterfaceState { + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) } self.canDeleteMessagesDisposable.set(nil) } else if let context = self.context { @@ -42,8 +42,8 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { |> deliverOnMainQueue).start(next: { [weak self] actions in if let strongSelf = self { strongSelf.actions = actions - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout, let interfaceState = strongSelf.presentationInterfaceState { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout, let interfaceState = strongSelf.presentationInterfaceState { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) } } })) @@ -154,8 +154,8 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { - self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) let panelHeight = defaultHeight(metrics: metrics) diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index d7657cb0fd..7724544ea2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -57,6 +57,25 @@ class ChatMessageStickerItemNode: ChatMessageItemView { private var enableSynchronousImageApply: Bool = false + override var visibility: ListViewItemNodeVisibility { + didSet { + let wasVisible = oldValue != .none + let isVisible = self.visibility != .none + + if wasVisible != isVisible { + self.visibilityStatus = isVisible + } + } + } + + private var visibilityStatus: Bool? { + didSet { + if self.visibilityStatus != oldValue { + self.replyInfoNode?.visibility = self.visibilityStatus == true + } + } + } + required init() { self.contextSourceNode = ContextExtractedContentContainingNode() self.containerNode = ContextControllerSourceNode() @@ -526,7 +545,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let (dateAndStatusSize, dateAndStatusApply) = statusSuggestedWidthAndContinue.1(statusSuggestedWidthAndContinue.0) var viaBotApply: (TextNodeLayout, () -> TextNode)? - var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? + var replyInfoApply: (CGSize, (Bool) -> ChatMessageReplyInfoNode)? var replyMarkup: ReplyMarkupMessageAttribute? var availableWidth = max(60.0, params.width - params.leftInset - params.rightInset - max(imageSize.width, 160.0) - 20.0 - layoutConstants.bubble.edgeInset * 2.0 - avatarInset - layoutConstants.bubble.contentInsets.left) @@ -570,7 +589,17 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId { } else { - replyInfoApply = makeReplyInfoLayout(item.presentationData, item.presentationData.strings, item.context, .standalone, replyMessage, item.message, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude)) + replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments( + presentationData: item.presentationData, + strings: item.presentationData.strings, + context: item.context, + type: .standalone, + message: replyMessage, + parentMessage: item.message, + constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude), + animationCache: item.controllerInteraction.presentationContext.animationCache, + animationRenderer: item.controllerInteraction.presentationContext.animationRenderer + )) } } else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty { replyMarkup = attribute @@ -752,7 +781,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } } - return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, _ in + return (ListViewItemNodeLayout(contentSize: layoutSize, insets: layoutInsets), { [weak self] animation, _, synchronousLoads in if let strongSelf = self { var transition: ContainedViewLayoutTransition = .immediate if case let .System(duration, _) = animation { @@ -882,7 +911,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } if let (replyInfoSize, replyInfoApply) = replyInfoApply { - let replyInfoNode = replyInfoApply() + let replyInfoNode = replyInfoApply(synchronousLoads) if strongSelf.replyInfoNode == nil { strongSelf.replyInfoNode = replyInfoNode strongSelf.contextSourceNode.contentNode.addSubnode(replyInfoNode) @@ -1487,17 +1516,17 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let localSourceContentFrame = CGRect( origin: CGPoint( - x: self.imageNode.frame.minX + self.imageNode.frame.size.width / 2.0 - stickerSource.imageNode.frame.size.width / 2.0, - y: self.imageNode.frame.minY + self.imageNode.frame.size.height / 2.0 - stickerSource.imageNode.frame.size.height / 2.0 + x: self.imageNode.frame.minX + self.imageNode.frame.size.width / 2.0 - stickerSource.sourceFrame.size.width / 2.0, + y: self.imageNode.frame.minY + self.imageNode.frame.size.height / 2.0 - stickerSource.sourceFrame.size.height / 2.0 ), - size: stickerSource.imageNode.frame.size + size: stickerSource.sourceFrame.size ) var snapshotView: UIView? if let animationNode = stickerSource.animationNode { snapshotView = animationNode.view.snapshotContentTree() } else { - snapshotView = stickerSource.imageNode.view.snapshotContentTree() + snapshotView = stickerSource.snapshotContentTree() } snapshotView?.frame = localSourceContentFrame @@ -1518,7 +1547,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { y: localSourceCenter.y - localSourceContentFrame.height / 2.0 ) - let sourceScale: CGFloat = stickerSource.imageNode.frame.height / self.imageNode.frame.height + let sourceScale: CGFloat = stickerSource.sourceFrame.height / self.imageNode.frame.height let offset = CGPoint( x: sourceCenter.x - self.imageNode.frame.midX, @@ -1554,8 +1583,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView { animationNode.layer.animateAlpha(from: 0.0, to: animationNode.alpha, duration: 0.4) } - stickerSource.imageNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) - stickerSource.imageNode.layer.animateAlpha(from: 0.0, to: stickerSource.imageNode.alpha, duration: 0.4) + if let sourceLayer = stickerSource.sourceLayer { + sourceLayer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) + sourceLayer.animateAlpha(from: 0.0, to: CGFloat(sourceLayer.opacity), duration: 0.4) + } if let placeholderNode = stickerSource.placeholderNode { placeholderNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 4bd4d9df65..2df9ca3c88 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -19,6 +19,7 @@ import AnimationCache import LottieAnimationCache import MultiAnimationRenderer import EmojiTextAttachmentView +import TextNodeWithEntities private final class CachedChatMessageText { let text: String @@ -46,28 +47,9 @@ private final class CachedChatMessageText { } } -private final class InlineStickerItem: Hashable { - let file: TelegramMediaFile - - init(file: TelegramMediaFile) { - self.file = file - } - - func hash(into hasher: inout Hasher) { - hasher.combine(self.file.fileId) - } - - static func ==(lhs: InlineStickerItem, rhs: InlineStickerItem) -> Bool { - if lhs.file.fileId != rhs.file.fileId { - return false - } - return true - } -} - class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { - private let textNode: TextNode - private var spoilerTextNode: TextNode? + private let textNode: TextNodeWithEntities + private var spoilerTextNode: TextNodeWithEntities? private var dustNode: InvisibleInkDustNode? private let textAccessibilityOverlayNode: TextAccessibilityOverlayNode @@ -76,42 +58,29 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private var textSelectionNode: TextSelectionNode? private var textHighlightingNodes: [LinkHighlightingNode] = [] - private var inlineStickerItemLayers: [InlineStickerItemLayer.Key: InlineStickerItemLayer] = [:] private var cachedChatMessageText: CachedChatMessageText? - private var isVisibleForAnimations: Bool { - return self.visibility != .none - } - override var visibility: ListViewItemNodeVisibility { didSet { - if !self.inlineStickerItemLayers.isEmpty { - if oldValue != self.visibility { - for (_, itemLayer) in self.inlineStickerItemLayers { - let isItemVisible: Bool - switch self.visibility { - case .none: - isItemVisible = false - case let .visible(_, subRect): - var subRect = subRect - subRect.origin.x = 0.0 - subRect.size.width = 10000.0 - if itemLayer.frame.intersects(subRect) { - isItemVisible = true - } else { - isItemVisible = false - } - } - itemLayer.isVisibleForAnimations = isItemVisible - } + if oldValue != self.visibility { + switch self.visibility { + case .none: + self.textNode.visibilityRect = nil + self.spoilerTextNode?.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + self.textNode.visibilityRect = subRect + self.spoilerTextNode?.visibilityRect = subRect } } } } required init() { - self.textNode = TextNode() + self.textNode = TextNodeWithEntities() self.statusNode = ChatMessageDateAndStatusNode() @@ -119,11 +88,11 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { super.init() - self.textNode.isUserInteractionEnabled = false - self.textNode.contentMode = .topLeft - self.textNode.contentsScale = UIScreenScale - self.textNode.displaysAsynchronously = true - self.addSubnode(self.textNode) + self.textNode.textNode.isUserInteractionEnabled = false + self.textNode.textNode.contentMode = .topLeft + self.textNode.textNode.contentsScale = UIScreenScale + self.textNode.textNode.displaysAsynchronously = true + self.addSubnode(self.textNode.textNode) self.addSubnode(self.textAccessibilityOverlayNode) self.textAccessibilityOverlayNode.openUrl = { [weak self] url in @@ -152,8 +121,8 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { - let textLayout = TextNode.asyncLayout(self.textNode) - let spoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) + let textLayout = TextNodeWithEntities.asyncLayout(self.textNode) + let spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode) let statusLayout = self.statusNode.asyncLayout() let currentCachedChatMessageText = self.cachedChatMessageText @@ -282,6 +251,10 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } } + + if let updatingMedia = item.attributes.updatingMedia { + messageEntities = updatingMedia.entities?.entities ?? [] + } } var entities: [MessageTextEntity]? @@ -334,45 +307,33 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let textFont = item.presentationData.messageFont if let entities = entities { - attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont) + attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, message: item.message) } else if !rawText.isEmpty { attributedText = NSAttributedString(string: rawText, font: textFont, textColor: messageTheme.primaryTextColor) } else { attributedText = NSAttributedString(string: " ", font: textFont, textColor: messageTheme.primaryTextColor) } - /*if let entities = entities { + if let entities = entities { let updatedString = NSMutableAttributedString(attributedString: attributedText) for entity in entities.sorted(by: { $0.range.lowerBound > $1.range.lowerBound }) { - guard case .AnimatedEmoji = entity.type else { + guard case let .CustomEmoji(stickerPack, fileId) = entity.type else { continue } let range = NSRange(location: entity.range.lowerBound, length: entity.range.upperBound - entity.range.lowerBound) - let substring = updatedString.attributedSubstring(from: range) + let currentDict = updatedString.attributes(at: range.lowerBound, effectiveRange: nil) + var updatedAttributes: [NSAttributedString.Key: Any] = currentDict + updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile) - let emoji = substring.string.basicEmoji.0 - - var emojiFile: TelegramMediaFile? - emojiFile = item.associatedData.animatedEmojiStickers[emoji]?.first?.file - if emojiFile == nil { - emojiFile = item.associatedData.animatedEmojiStickers[emoji.strippedEmoji]?.first?.file - } - - if let emojiFile = emojiFile { - let currentDict = updatedString.attributes(at: range.lowerBound, effectiveRange: nil) - var updatedAttributes: [NSAttributedString.Key: Any] = currentDict - updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor - updatedAttributes[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(file: emojiFile) - - let insertString = NSAttributedString(string: "[\u{00a0}\u{00a0}]", attributes: updatedAttributes) - updatedString.replaceCharacters(in: range, with: insertString) - } + let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) + updatedString.replaceCharacters(in: range, with: insertString) } attributedText = updatedString - }*/ + } let cutout: TextNodeCutout? = nil @@ -380,9 +341,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor)) - let spoilerTextLayoutAndApply: (TextNodeLayout, () -> TextNode)? + let spoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)? if !textLayout.spoilers.isEmpty { - spoilerTextLayoutAndApply = spoilerTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor, displaySpoilers: true)) + spoilerTextLayoutAndApply = spoilerTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: textInsets, lineColor: messageTheme.accentControlColor, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true)) } else { spoilerTextLayoutAndApply = nil } @@ -449,65 +410,65 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { boundingSize.width += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right boundingSize.height += layoutConstants.text.bubbleInsets.top + layoutConstants.text.bubbleInsets.bottom - return (boundingSize, { [weak self] animation, _, _ in + return (boundingSize, { [weak self] animation, synchronousLoads, _ in if let strongSelf = self { strongSelf.item = item if let updatedCachedChatMessageText = updatedCachedChatMessageText { strongSelf.cachedChatMessageText = updatedCachedChatMessageText } - let cachedLayout = strongSelf.textNode.cachedLayout + let cachedLayout = strongSelf.textNode.textNode.cachedLayout if case .System = animation { if let cachedLayout = cachedLayout { if !cachedLayout.areLinesEqual(to: textLayout) { - if let textContents = strongSelf.textNode.contents { + if let textContents = strongSelf.textNode.textNode.contents { let fadeNode = ASDisplayNode() fadeNode.displaysAsynchronously = false fadeNode.contents = textContents - fadeNode.frame = strongSelf.textNode.frame + fadeNode.frame = strongSelf.textNode.textNode.frame fadeNode.isLayerBacked = true strongSelf.addSubnode(fadeNode) fadeNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak fadeNode] _ in fadeNode?.removeFromSupernode() }) - strongSelf.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) + strongSelf.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) } } } } - let _ = textApply() - animation.animator.updateFrame(layer: strongSelf.textNode.layer, frame: textFrame, completion: nil) + let _ = textApply(TextNodeWithEntities.Arguments(context: item.context, cache: item.controllerInteraction.presentationContext.animationCache, renderer: item.controllerInteraction.presentationContext.animationRenderer, placeholderColor: messageTheme.mediaPlaceholderColor, attemptSynchronous: synchronousLoads)) + animation.animator.updateFrame(layer: strongSelf.textNode.textNode.layer, frame: textFrame, completion: nil) if let (_, spoilerTextApply) = spoilerTextLayoutAndApply { - let spoilerTextNode = spoilerTextApply() + let spoilerTextNode = spoilerTextApply(TextNodeWithEntities.Arguments(context: item.context, cache: item.controllerInteraction.presentationContext.animationCache, renderer: item.controllerInteraction.presentationContext.animationRenderer, placeholderColor: messageTheme.mediaPlaceholderColor, attemptSynchronous: synchronousLoads)) if strongSelf.spoilerTextNode == nil { - spoilerTextNode.alpha = 0.0 - spoilerTextNode.isUserInteractionEnabled = false - spoilerTextNode.contentMode = .topLeft - spoilerTextNode.contentsScale = UIScreenScale - spoilerTextNode.displaysAsynchronously = false - strongSelf.insertSubnode(spoilerTextNode, aboveSubnode: strongSelf.textAccessibilityOverlayNode) + spoilerTextNode.textNode.alpha = 0.0 + spoilerTextNode.textNode.isUserInteractionEnabled = false + spoilerTextNode.textNode.contentMode = .topLeft + spoilerTextNode.textNode.contentsScale = UIScreenScale + spoilerTextNode.textNode.displaysAsynchronously = false + strongSelf.insertSubnode(spoilerTextNode.textNode, aboveSubnode: strongSelf.textAccessibilityOverlayNode) strongSelf.spoilerTextNode = spoilerTextNode } - strongSelf.spoilerTextNode?.frame = textFrame + strongSelf.spoilerTextNode?.textNode.frame = textFrame let dustNode: InvisibleInkDustNode if let current = strongSelf.dustNode { dustNode = current } else { - dustNode = InvisibleInkDustNode(textNode: spoilerTextNode) + dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode) strongSelf.dustNode = dustNode - strongSelf.insertSubnode(dustNode, aboveSubnode: spoilerTextNode) + strongSelf.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode) } dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0) dustNode.update(size: dustNode.frame.size, color: messageTheme.secondaryTextColor, textColor: messageTheme.primaryTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }) } else if let spoilerTextNode = strongSelf.spoilerTextNode { strongSelf.spoilerTextNode = nil - spoilerTextNode.removeFromSupernode() + spoilerTextNode.textNode.removeFromSupernode() if let dustNode = strongSelf.dustNode { strongSelf.dustNode = nil @@ -515,6 +476,18 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } + switch strongSelf.visibility { + case .none: + strongSelf.textNode.visibilityRect = nil + strongSelf.spoilerTextNode?.visibilityRect = nil + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + strongSelf.textNode.visibilityRect = subRect + strongSelf.spoilerTextNode?.visibilityRect = subRect + } + if let textSelectionNode = strongSelf.textSelectionNode { let shouldUpdateLayout = textSelectionNode.frame.size != textFrame.size textSelectionNode.frame = textFrame @@ -525,8 +498,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } strongSelf.textAccessibilityOverlayNode.frame = textFrame strongSelf.textAccessibilityOverlayNode.cachedLayout = textLayout - - strongSelf.updateInlineStickers(context: item.context, cache: item.controllerInteraction.presentationContext.animationCache, renderer: item.controllerInteraction.presentationContext.animationRenderer, textLayout: textLayout, placeholderColor: messageTheme.mediaPlaceholderColor) + if let statusSizeAndApply = statusSizeAndApply { animation.animator.updateFrame(layer: strongSelf.statusNode.layer, frame: CGRect(origin: CGPoint(x: textFrameWithoutInsets.minX, y: textFrameWithoutInsets.maxY), size: statusSizeAndApply.0), completion: nil) @@ -557,73 +529,29 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } - private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor) { - var nextIndexById: [MediaId: Int] = [:] - var validIds: [InlineStickerItemLayer.Key] = [] - - if let textLayout = textLayout { - for item in textLayout.embeddedItems { - if let stickerItem = item.value as? InlineStickerItem { - let index: Int - if let currentNext = nextIndexById[stickerItem.file.fileId] { - index = currentNext - } else { - index = 0 - } - nextIndexById[stickerItem.file.fileId] = index + 1 - let id = InlineStickerItemLayer.Key(id: stickerItem.file.fileId, index: index) - validIds.append(id) - - let itemLayer: InlineStickerItemLayer - if let current = self.inlineStickerItemLayers[id] { - itemLayer = current - } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor) - self.inlineStickerItemLayers[id] = itemLayer - self.textNode.layer.addSublayer(itemLayer) - itemLayer.isVisibleForAnimations = self.isVisibleForAnimations - } - - itemLayer.frame = CGRect(origin: item.rect.offsetBy(dx: textLayout.insets.left, dy: textLayout.insets.top + 0.0).center, size: CGSize()).insetBy(dx: -12.0, dy: -12.0) - } - } - } - - var removeKeys: [InlineStickerItemLayer.Key] = [] - for (key, itemLayer) in self.inlineStickerItemLayers { - if !validIds.contains(key) { - removeKeys.append(key) - itemLayer.removeFromSuperlayer() - } - } - for key in removeKeys { - self.inlineStickerItemLayers.removeValue(forKey: key) - } - } - override func animateInsertion(_ currentTimestamp: Double, duration: Double) { - self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } override func animateAdded(_ currentTimestamp: Double, duration: Double) { - self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } override func animateRemoved(_ currentTimestamp: Double, duration: Double) { - self.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + self.textNode.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) } override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction { - let textNodeFrame = self.textNode.frame - if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + let textNodeFrame = self.textNode.textNode.frame + if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !(self.dustNode?.isRevealed ?? true) { return .none } else if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { var concealed = true - if let (attributeText, fullText) = self.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { + if let (attributeText, fullText) = self.textNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText) } return .url(url: url, concealed: concealed) @@ -680,8 +608,8 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { var rects: [CGRect]? var spoilerRects: [CGRect]? if let point = point { - let textNodeFrame = self.textNode.frame - if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + let textNodeFrame = self.textNode.textNode.frame + if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { let possibleNames: [String] = [ TelegramTextAttributes.URL, TelegramTextAttributes.PeerMention, @@ -693,12 +621,12 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { ] for name in possibleNames { if let _ = attributes[NSAttributedString.Key(rawValue: name)] { - rects = self.textNode.attributeRects(name: name, at: index) + rects = self.textNode.textNode.attributeRects(name: name, at: index) break } } if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)] { - spoilerRects = self.textNode.attributeRects(name: TelegramTextAttributes.Spoiler, at: index) + spoilerRects = self.textNode.textNode.attributeRects(name: TelegramTextAttributes.Spoiler, at: index) } } } @@ -712,9 +640,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } else { linkHighlightingNode = LinkHighlightingNode(color: item.message.effectivelyIncoming(item.context.account.peerId) ? item.presentationData.theme.theme.chat.message.incoming.linkHighlightColor : item.presentationData.theme.theme.chat.message.outgoing.linkHighlightColor) self.linkHighlightingNode = linkHighlightingNode - self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode) + self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode.textNode) } - linkHighlightingNode.frame = self.textNode.frame + linkHighlightingNode.frame = self.textNode.textNode.frame linkHighlightingNode.updateRects(rects) } else if let linkHighlightingNode = self.linkHighlightingNode { self.linkHighlightingNode = nil @@ -727,16 +655,16 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { override func peekPreviewContent(at point: CGPoint) -> (Message, ChatMessagePeekPreviewContent)? { if let item = self.item { - let textNodeFrame = self.textNode.frame - if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + let textNodeFrame = self.textNode.textNode.frame + if let (index, attributes) = self.textNode.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { if let value = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { - if let rects = self.textNode.attributeRects(name: TelegramTextAttributes.URL, at: index), !rects.isEmpty { + if let rects = self.textNode.textNode.attributeRects(name: TelegramTextAttributes.URL, at: index), !rects.isEmpty { var rect = rects[0] for i in 1 ..< rects.count { rect = rect.union(rects[i]) } var concealed = true - if let (attributeText, fullText) = self.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { + if let (attributeText, fullText) = self.textNode.textNode.attributeSubstring(name: TelegramTextAttributes.URL, index: index) { concealed = !doesUrlMatchText(url: value, text: attributeText, fullText: fullText) } return (item.message, .url(self, rect, value, concealed)) @@ -753,7 +681,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } let rectsSet: [[CGRect]] if let text = text, let messages = messages, !text.isEmpty, messages.contains(item.message.index) { - rectsSet = self.textNode.textRangesRects(text: text) + rectsSet = self.textNode.textNode.textRangesRects(text: text) } else { rectsSet = [] } @@ -765,9 +693,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } else { textHighlightNode = LinkHighlightingNode(color: item.message.effectivelyIncoming(item.context.account.peerId) ? item.presentationData.theme.theme.chat.message.incoming.textHighlightColor : item.presentationData.theme.theme.chat.message.outgoing.textHighlightColor) self.textHighlightingNodes.append(textHighlightNode) - self.insertSubnode(textHighlightNode, belowSubnode: self.textNode) + self.insertSubnode(textHighlightNode, belowSubnode: self.textNode.textNode) } - textHighlightNode.frame = self.textNode.frame + textHighlightNode.frame = self.textNode.textNode.frame textHighlightNode.updateRects(rects) } for i in (rectsSet.count ..< self.textHighlightingNodes.count).reversed() { @@ -802,7 +730,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { knobColor = item.presentationData.theme.theme.chat.message.outgoing.textSelectionKnobColor } - let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor), strings: item.presentationData.strings, textNode: self.textNode, updateIsActive: { [weak self] value in + let textSelectionNode = TextSelectionNode(theme: TextSelectionTheme(selection: selectionColor, knob: knobColor), strings: item.presentationData.strings, textNode: self.textNode.textNode, updateIsActive: { [weak self] value in self?.updateIsTextSelectionActive?(value) }, present: { [weak self] c, a in self?.item?.controllerInteraction.presentGlobalOverlayController(c, a) @@ -813,7 +741,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { item.controllerInteraction.performTextSelectionAction(item.message.stableId, text, action) }) textSelectionNode.updateRange = { [weak self] selectionRange in - if let strongSelf = self, let dustNode = strongSelf.dustNode, !dustNode.isRevealed, let textLayout = strongSelf.textNode.cachedLayout, !textLayout.spoilers.isEmpty, let selectionRange = selectionRange { + if let strongSelf = self, let dustNode = strongSelf.dustNode, !dustNode.isRevealed, let textLayout = strongSelf.textNode.textNode.cachedLayout, !textLayout.spoilers.isEmpty, let selectionRange = selectionRange { for (spoilerRange, _) in textLayout.spoilers { if let intersection = selectionRange.intersection(spoilerRange), intersection.length > 0 { dustNode.update(revealed: true) @@ -824,9 +752,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } self.textSelectionNode = textSelectionNode self.addSubnode(textSelectionNode) - self.insertSubnode(textSelectionNode.highlightAreaNode, belowSubnode: self.textNode) - textSelectionNode.frame = self.textNode.frame - textSelectionNode.highlightAreaNode.frame = self.textNode.frame + self.insertSubnode(textSelectionNode.highlightAreaNode, belowSubnode: self.textNode.textNode) + textSelectionNode.frame = self.textNode.textNode.frame + textSelectionNode.highlightAreaNode.frame = self.textNode.textNode.frame } } else { if let textSelectionNode = self.textSelectionNode { @@ -862,14 +790,14 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { sourceView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak sourceView] _ in sourceView?.removeFromSuperview() }) - self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.08) + self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.08) let offset = CGPoint( - x: sourceView.frame.minX - (self.textNode.frame.minX - 0.0), - y: sourceView.frame.minY - (self.textNode.frame.minY - 3.0) - scrollOffset + x: sourceView.frame.minX - (self.textNode.textNode.frame.minX - 0.0), + y: sourceView.frame.minY - (self.textNode.textNode.frame.minY - 3.0) - scrollOffset ) - transition.vertical.animatePositionAdditive(node: self.textNode, offset: offset) + transition.vertical.animatePositionAdditive(node: self.textNode.textNode, offset: offset) transition.updatePosition(layer: sourceView.layer, position: CGPoint(x: sourceView.layer.position.x - offset.x, y: sourceView.layer.position.y - offset.y)) self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) diff --git a/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift index dfa894b6d0..8476cc2a3d 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift @@ -10,6 +10,14 @@ import Postbox import TelegramCore import ReactionSelectionNode +private func convertAnimatingSourceRect(_ rect: CGRect, fromView: UIView, toView: UIView?) -> CGRect { + if let presentationLayer = fromView.layer.presentation() { + return presentationLayer.convert(rect, to: toView?.layer) + } else { + return fromView.layer.convert(rect, to: toView?.layer) + } +} + private final class OverlayTransitionContainerNode: ViewControllerTracingNode { override init() { super.init() @@ -111,17 +119,51 @@ public final class ChatMessageTransitionNode: ASDisplayNode { } final class Sticker { - let imageNode: TransformImageNode + let imageNode: TransformImageNode? let animationNode: AnimatedStickerNode? let placeholderNode: ASDisplayNode? + let imageLayer: CALayer? let relativeSourceRect: CGRect + + var sourceFrame: CGRect { + if let imageNode = self.imageNode { + return imageNode.frame + } else if let imageLayer = self.imageLayer { + return imageLayer.bounds + } else { + return CGRect(origin: CGPoint(), size: relativeSourceRect.size) + } + } + + var sourceLayer: CALayer? { + if let imageNode = self.imageNode { + return imageNode.layer + } else if let imageLayer = self.imageLayer { + return imageLayer + } else { + return nil + } + } - init(imageNode: TransformImageNode, animationNode: AnimatedStickerNode?, placeholderNode: ASDisplayNode?, relativeSourceRect: CGRect) { + init(imageNode: TransformImageNode?, animationNode: AnimatedStickerNode?, placeholderNode: ASDisplayNode?, imageLayer: CALayer?, relativeSourceRect: CGRect) { self.imageNode = imageNode self.animationNode = animationNode self.placeholderNode = placeholderNode + self.imageLayer = imageLayer self.relativeSourceRect = relativeSourceRect } + + func snapshotContentTree() -> UIView? { + if let animationNode = self.animationNode { + return animationNode.view.snapshotContentTree() + } else if let imageNode = self.imageNode { + return imageNode.view.snapshotContentTree() + } else if let sourceLayer = self.imageLayer { + return sourceLayer.snapshotContentTreeAsView() + } else { + return nil + } + } } enum Source { @@ -142,6 +184,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode { enum StickerInput { case inputPanel(itemNode: ChatMediaInputStickerGridItemNode) case mediaPanel(itemNode: HorizontalStickerGridItemNode) + case universal(sourceContainerView: UIView, sourceRect: CGRect, sourceLayer: CALayer) case inputPanelSearch(itemNode: StickerPaneSearchStickerItemNode) case emptyPanel(itemNode: ChatEmptyNodeStickerContentNode) } @@ -388,16 +431,19 @@ public final class ChatMessageTransitionNode: ASDisplayNode { let sourceAbsoluteRect: CGRect switch stickerMediaInput { case let .inputPanel(sourceItemNode): - stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: sourceItemNode.placeholderNode, relativeSourceRect: sourceItemNode.imageNode.frame) - sourceAbsoluteRect = sourceItemNode.view.convert(stickerSource.imageNode.frame, to: self.view) + stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: sourceItemNode.placeholderNode, imageLayer: nil, relativeSourceRect: sourceItemNode.imageNode.frame) + sourceAbsoluteRect = sourceItemNode.view.convert(sourceItemNode.imageNode.frame, to: self.view) case let .mediaPanel(sourceItemNode): - stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: sourceItemNode.placeholderNode, relativeSourceRect: sourceItemNode.imageNode.frame) - sourceAbsoluteRect = sourceItemNode.view.convert(stickerSource.imageNode.frame, to: self.view) + stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: sourceItemNode.placeholderNode, imageLayer: nil, relativeSourceRect: sourceItemNode.imageNode.frame) + sourceAbsoluteRect = sourceItemNode.view.convert(sourceItemNode.imageNode.frame, to: self.view) + case let .universal(sourceContainerView, sourceRect, sourceLayer): + stickerSource = Sticker(imageNode: nil, animationNode: nil, placeholderNode: nil, imageLayer: sourceLayer, relativeSourceRect: sourceLayer.frame) + sourceAbsoluteRect = convertAnimatingSourceRect(sourceRect, fromView: sourceContainerView, toView: self.view) case let .inputPanelSearch(sourceItemNode): - stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: nil, relativeSourceRect: sourceItemNode.imageNode.frame) - sourceAbsoluteRect = sourceItemNode.view.convert(stickerSource.imageNode.frame, to: self.view) + stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: nil, imageLayer: nil, relativeSourceRect: sourceItemNode.imageNode.frame) + sourceAbsoluteRect = sourceItemNode.view.convert(sourceItemNode.imageNode.frame, to: self.view) case let .emptyPanel(sourceItemNode): - stickerSource = Sticker(imageNode: sourceItemNode.stickerNode.imageNode, animationNode: sourceItemNode.stickerNode.animationNode, placeholderNode: nil, relativeSourceRect: sourceItemNode.stickerNode.imageNode.frame) + stickerSource = Sticker(imageNode: sourceItemNode.stickerNode.imageNode, animationNode: sourceItemNode.stickerNode.animationNode, placeholderNode: nil, imageLayer: nil, relativeSourceRect: sourceItemNode.stickerNode.imageNode.frame) sourceAbsoluteRect = sourceItemNode.stickerNode.view.convert(sourceItemNode.stickerNode.imageNode.frame, to: self.view) } @@ -442,7 +488,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode { self.containerNode.layer.animatePosition(from: CGPoint(x: sourceAbsoluteRect.midX - targetAbsoluteRect.midX, y: 0.0), to: CGPoint(), duration: horizontalDuration, delay: delay, mediaTimingFunction: ChatMessageTransitionNode.horizontalAnimationCurve.mediaTimingFunction, additive: true) switch stickerMediaInput { - case .inputPanel: + case .inputPanel, .universal: break case let .mediaPanel(sourceItemNode): sourceItemNode.isHidden = true diff --git a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift index f7e60862b9..3a38fa9ecb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -373,7 +373,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode { displayLine = false } - let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, item.chatLocation, title, subtitle, text, entities, mediaAndFlags, badge, actionIcon, actionTitle, displayLine, layoutConstants, preparePosition, constrainedSize) + let (initialWidth, continueLayout) = contentNodeLayout(item.presentationData, item.controllerInteraction.automaticMediaDownloadSettings, item.associatedData, item.attributes, item.context, item.controllerInteraction, item.message, item.read, item.chatLocation, title, subtitle, text, entities, mediaAndFlags, badge, actionIcon, actionTitle, displayLine, layoutConstants, preparePosition, constrainedSize, item.controllerInteraction.presentationContext.animationCache, item.controllerInteraction.presentationContext.animationRenderer) let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 8.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none) diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index f3843008d4..c07d3aa24c 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -18,6 +18,9 @@ import RadialStatusNode import InvisibleInkDustNode import TextFormat import ChatPresentationInterfaceState +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer private enum PinnedMessageAnimation { case slideToTop @@ -52,8 +55,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { private let contentTextContainer: ASDisplayNode private let lineNode: AnimatedNavigationStripeNode private let titleNode: AnimatedCountLabelNode - private let textNode: TextNode - private var spoilerTextNode: TextNode? + private let textNode: TextNodeWithEntities + private var spoilerTextNode: TextNodeWithEntities? private var dustNode: InvisibleInkDustNode? private let actionButton: HighlightableButtonNode private let actionButtonTitleNode: ImmediateTextNode @@ -73,6 +76,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { private let fetchDisposable = MetaDisposable() private var statusDisposable: Disposable? + + private let animationCache: AnimationCache? + private let animationRenderer: MultiAnimationRenderer? private let queue = Queue() @@ -85,8 +91,10 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { return result } - init(context: AccountContext) { + init(context: AccountContext, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { self.context = context + self.animationCache = animationCache + self.animationRenderer = animationRenderer self.tapButton = HighlightTrackingButtonNode() @@ -133,9 +141,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { self.titleNode.isUserInteractionEnabled = false self.titleNode.reverseAnimationDirection = true - self.textNode = TextNode() - self.textNode.displaysAsynchronously = false - self.textNode.isUserInteractionEnabled = false + self.textNode = TextNodeWithEntities() + self.textNode.textNode.displaysAsynchronously = false + self.textNode.textNode.isUserInteractionEnabled = false self.imageNode = TransformImageNode() self.imageNode.contentAnimations = [.subsequentUpdates] @@ -149,15 +157,15 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { if highlighted { strongSelf.titleNode.layer.removeAnimation(forKey: "opacity") strongSelf.titleNode.alpha = 0.4 - strongSelf.textNode.layer.removeAnimation(forKey: "opacity") - strongSelf.textNode.alpha = 0.4 + strongSelf.textNode.textNode.layer.removeAnimation(forKey: "opacity") + strongSelf.textNode.textNode.alpha = 0.4 strongSelf.lineNode.layer.removeAnimation(forKey: "opacity") strongSelf.lineNode.alpha = 0.4 } else { strongSelf.titleNode.alpha = 1.0 strongSelf.titleNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) - strongSelf.textNode.alpha = 1.0 - strongSelf.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + strongSelf.textNode.textNode.alpha = 1.0 + strongSelf.textNode.textNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) strongSelf.lineNode.alpha = 1.0 strongSelf.lineNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) } @@ -186,7 +194,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { self.clippingContainer.addSubnode(self.contentContainer) self.contextContainer.addSubnode(self.lineNode) self.contentTextContainer.addSubnode(self.titleNode) - self.contentTextContainer.addSubnode(self.textNode) + self.contentTextContainer.addSubnode(self.textNode.textNode) self.contentContainer.addSubnode(self.contentTextContainer) self.imageNodeContainer.addSubnode(self.imageNode) @@ -495,7 +503,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { if let animation = animation { animationTransition = .animated(duration: 0.2, curve: .easeInOut) - if let copyView = self.textNode.view.snapshotView(afterScreenUpdates: false) { + if let copyView = self.textNode.textNode.view.snapshotView(afterScreenUpdates: false) { let offset: CGFloat switch animation { case .slideToTop: @@ -504,20 +512,20 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { offset = 10.0 } - copyView.frame = self.textNode.frame - self.textNode.view.superview?.addSubview(copyView) + copyView.frame = self.textNode.textNode.frame + self.textNode.textNode.view.superview?.addSubview(copyView) copyView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: offset), duration: 0.2, removeOnCompletion: false, additive: true) copyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak copyView] _ in copyView?.removeFromSuperview() }) - self.textNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -offset), to: CGPoint(), duration: 0.2, additive: true) - self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.textNode.textNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -offset), to: CGPoint(), duration: 0.2, additive: true) + self.textNode.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } } let makeTitleLayout = self.titleNode.asyncLayout() - let makeTextLayout = TextNode.asyncLayout(self.textNode) - let makeSpoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) + let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) + let makeSpoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode) let imageNodeLayout = self.imageNode.asyncLayout() let previousMediaReference = self.previousMediaReference @@ -640,28 +648,29 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { let textFont = Font.regular(15.0) if isText { let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in - if case .Spoiler = entity.type { + switch entity.type { + case .Spoiler, .CustomEmoji: return true - } else { + default: return false } } let textColor = theme.chat.inputPanel.primaryTextColor if entities.count > 0 { - messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) + messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message) } else { - messageText = NSAttributedString(string: foldLineBreaks(textString), font: textFont, textColor: textColor) + messageText = NSAttributedString(string: foldLineBreaks(textString.string), font: textFont, textColor: textColor) } } else { - messageText = NSAttributedString(string: foldLineBreaks(textString), font: textFont, textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor) + messageText = NSAttributedString(string: foldLineBreaks(textString.string), font: textFont, textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor) } let textConstrainedSize = CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude) let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0))) - let spoilerTextLayoutAndApply: (TextNodeLayout, () -> TextNode)? + let spoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)? if !textLayout.spoilers.isEmpty { - spoilerTextLayoutAndApply = makeSpoilerTextLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0), displaySpoilers: true)) + spoilerTextLayoutAndApply = makeSpoilerTextLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0), displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true)) } else { spoilerTextLayoutAndApply = nil } @@ -669,7 +678,18 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { Queue.mainQueue().async { if let strongSelf = self { let _ = titleApply(animation != nil) - let _ = textApply() + + var textArguments: TextNodeWithEntities.Arguments? + if let cache = strongSelf.animationCache, let renderer = strongSelf.animationRenderer { + textArguments = TextNodeWithEntities.Arguments( + context: strongSelf.context, + cache: cache, + renderer: renderer, + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false + ) + } + let _ = textApply(textArguments) strongSelf.previousMediaReference = updatedMediaReference @@ -678,36 +698,36 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 5.0), size: titleLayout.size) let textFrame = CGRect(origin: CGPoint(x: 0.0, y: 23.0), size: textLayout.size) - strongSelf.textNode.frame = textFrame + strongSelf.textNode.textNode.frame = textFrame if let (_, spoilerTextApply) = spoilerTextLayoutAndApply { - let spoilerTextNode = spoilerTextApply() + let spoilerTextNode = spoilerTextApply(textArguments) if strongSelf.spoilerTextNode == nil { - spoilerTextNode.alpha = 0.0 - spoilerTextNode.isUserInteractionEnabled = false - spoilerTextNode.contentMode = .topLeft - spoilerTextNode.contentsScale = UIScreenScale - spoilerTextNode.displaysAsynchronously = false - strongSelf.contentTextContainer.insertSubnode(spoilerTextNode, aboveSubnode: strongSelf.textNode) + spoilerTextNode.textNode.alpha = 0.0 + spoilerTextNode.textNode.isUserInteractionEnabled = false + spoilerTextNode.textNode.contentMode = .topLeft + spoilerTextNode.textNode.contentsScale = UIScreenScale + spoilerTextNode.textNode.displaysAsynchronously = false + strongSelf.contentTextContainer.insertSubnode(spoilerTextNode.textNode, aboveSubnode: strongSelf.textNode.textNode) strongSelf.spoilerTextNode = spoilerTextNode } - strongSelf.spoilerTextNode?.frame = textFrame + strongSelf.spoilerTextNode?.textNode.frame = textFrame let dustNode: InvisibleInkDustNode if let current = strongSelf.dustNode { dustNode = current } else { - dustNode = InvisibleInkDustNode(textNode: spoilerTextNode) + dustNode = InvisibleInkDustNode(textNode: spoilerTextNode.textNode) strongSelf.dustNode = dustNode - strongSelf.contentTextContainer.insertSubnode(dustNode, aboveSubnode: spoilerTextNode) + strongSelf.contentTextContainer.insertSubnode(dustNode, aboveSubnode: spoilerTextNode.textNode) } dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0) dustNode.update(size: dustNode.frame.size, color: theme.chat.inputPanel.secondaryTextColor, textColor: theme.chat.inputPanel.primaryTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: textLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }) } else if let spoilerTextNode = strongSelf.spoilerTextNode { strongSelf.spoilerTextNode = nil - spoilerTextNode.removeFromSupernode() + spoilerTextNode.textNode.removeFromSupernode() if let dustNode = strongSelf.dustNode { strongSelf.dustNode = nil @@ -715,6 +735,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { } } + strongSelf.textNode.visibilityRect = CGRect.infinite + strongSelf.spoilerTextNode?.visibilityRect = CGRect.infinite + let lineFrame = CGRect(origin: CGPoint(x: contentLeftInset, y: 0.0), size: CGSize(width: 2.0, height: panelHeight)) animationTransition.updateFrame(node: strongSelf.lineNode, frame: lineFrame) strongSelf.lineNode.update( diff --git a/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift b/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift index be7b14fd58..fb9bf5ab34 100644 --- a/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift @@ -2127,7 +2127,7 @@ private class MessageContentNode: ASDisplayNode, ContentNode { let attributedText: NSAttributedString if let entities = entities { - attributedText = stringWithAppliedEntities(message.text, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: fixedFont, blockQuoteFont: blockQuoteFont, underlineLinks: false) + attributedText = stringWithAppliedEntities(message.text, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseFont: textFont, linkFont: textFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: fixedFont, blockQuoteFont: blockQuoteFont, underlineLinks: false, message: message) } else if !message.text.isEmpty { attributedText = NSAttributedString(string: message.text, font: textFont, textColor: messageTheme.primaryTextColor) } else { diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift index eaa4b84307..b700e2524d 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift @@ -105,7 +105,7 @@ final class ChatRecentActionsController: TelegramBaseController { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -153,6 +153,8 @@ final class ChatRecentActionsController: TelegramBaseController { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index fa72a7a018..5fa9774f2f 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -261,7 +261,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, activateMessagePinch: { _ in }, openMessageContextActions: { _, _, _, _ in }, navigateToMessage: { _, _ in }, navigateToMessageStandalone: { _ in - }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _, _ in + }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { [weak self] url, _, _, _ in self?.openUrl(url) }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { [weak self] message, associatedData in if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { @@ -517,7 +517,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in @@ -537,6 +537,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, openWebView: { _, _, _, _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { + }, dismissTextInput: { }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false), presentationContext: ChatPresentationContext(context: context, backgroundNode: self.backgroundNode)) self.controllerInteraction = controllerInteraction @@ -898,7 +899,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { if let navigationController = strongSelf.getNavigationController() { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(message: replyThreadMessage), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) } - case let .stickerPack(name): + case let .stickerPack(name, type): + let _ = type let packReference: StickerPackReference = .name(name) strongSelf.presentController(StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.getNavigationController()), .window(.root), nil) case let .invoice(slug, invoice): diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index 97974dd8fe..c149e6447e 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -113,7 +113,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { peers[peer.id] = peer let action = TelegramMediaActionType.titleUpdated(title: new) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeAbout(prev, new): var peers = SimpleDictionary() @@ -144,14 +144,14 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: let peers = SimpleDictionary() let attributes: [MessageAttribute] = [] - let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousDescription(prevMessage) : nil) } case let .changeUsername(prev, new): @@ -182,7 +182,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) } let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: var previousAttributes: [MessageAttribute] = [] @@ -200,8 +200,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)])) } - let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil) } case let .changePhoto(_, new): @@ -220,7 +220,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } let action = TelegramMediaActionType.photoUpdated(image: photo) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .toggleInvites(value): var peers = SimpleDictionary() @@ -247,7 +247,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .toggleSignatures(value): var peers = SimpleDictionary() @@ -274,7 +274,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .updatePinned(message): switch self.id.contentIndex { @@ -305,7 +305,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: if let message = message { @@ -323,7 +323,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } else { var peers = SimpleDictionary() @@ -345,7 +345,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } } @@ -390,7 +390,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: var peers = SimpleDictionary() @@ -407,7 +407,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.text.isEmpty || !message.text.isEmpty ? .eventLogPreviousMessage(filterOriginalMessageFlags(prev)) : nil) } case let .deleteMessage(message): @@ -433,7 +433,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: var peers = SimpleDictionary() @@ -457,7 +457,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } case .participantJoin, .participantLeave: @@ -475,7 +475,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } else { action = TelegramMediaActionType.removedMembers(peerIds: [self.entry.event.peerId]) } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .participantInvite(participant): var peers = SimpleDictionary() @@ -492,7 +492,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action: TelegramMediaActionType action = TelegramMediaActionType.addedMembers(peerIds: [participant.peer.id]) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .participantToggleBan(prev, new): var peers = SimpleDictionary() @@ -622,7 +622,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .participantToggleAdmin(prev, new): var peers = SimpleDictionary() @@ -855,7 +855,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeStickerPack(_, new): var peers = SimpleDictionary() @@ -884,7 +884,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .togglePreHistoryHidden(value): var peers = SimpleDictionary() @@ -914,7 +914,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .updateDefaultBannedRights(prev, new): var peers = SimpleDictionary() @@ -972,7 +972,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .pollStopped(message): switch self.id.contentIndex { @@ -1000,7 +1000,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: var peers = SimpleDictionary() @@ -1017,7 +1017,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: nil) } case let .linkedPeerUpdated(previous, updated): @@ -1073,7 +1073,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeGeoLocation(_, updated): var peers = SimpleDictionary() @@ -1095,12 +1095,12 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let mediaMap = TelegramMediaMap(latitude: updated.latitude, longitude: updated.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } else { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } case let .updateSlowmode(_, newValue): @@ -1131,7 +1131,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .startGroupCall, .endGroupCall: var peers = SimpleDictionary() @@ -1168,7 +1168,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .groupCallUpdateParticipantMuteStatus(participantId, isMuted): var peers = SimpleDictionary() @@ -1202,7 +1202,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .updateGroupCallSettings(joinMuted): var peers = SimpleDictionary() @@ -1231,7 +1231,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .groupCallUpdateParticipantVolume(participantId, volume): var peers = SimpleDictionary() @@ -1262,7 +1262,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .deleteExportedInvitation(invite): var peers = SimpleDictionary() @@ -1288,7 +1288,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .revokeExportedInvitation(invite): var peers = SimpleDictionary() @@ -1314,7 +1314,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .editExportedInvitation(_, updatedInvite): var peers = SimpleDictionary() @@ -1340,7 +1340,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .participantJoinedViaInvite(invite): var peers = SimpleDictionary() @@ -1366,7 +1366,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeHistoryTTL(_, updatedValue): var peers = SimpleDictionary() @@ -1397,7 +1397,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeAvailableReactions(_, updatedValue): var peers = SimpleDictionary() @@ -1429,7 +1429,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .changeTheme(_, updatedValue): var peers = SimpleDictionary() @@ -1460,7 +1460,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .participantJoinByRequest(invite, approvedBy): var peers = SimpleDictionary() @@ -1500,7 +1500,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .toggleCopyProtection(value): var peers = SimpleDictionary() @@ -1527,7 +1527,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) } let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case let .sendMessage(message): switch self.id.contentIndex { @@ -1552,7 +1552,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { }, to: &text, entities: &entities) let action = TelegramMediaActionType.customText(text: text, entities: entities) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) case .content: var peers = SimpleDictionary() @@ -1569,7 +1569,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } } } - let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil)) } } diff --git a/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift index ef4e9a8f36..d5a11df5da 100644 --- a/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift @@ -135,7 +135,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { var updateWaveform = false if self.presentationInterfaceState?.recordedMediaPreview != interfaceState.recordedMediaPreview { diff --git a/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift index fe74f4e2d8..3f97a2f20e 100644 --- a/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatRestrictedInputPanelNode.swift @@ -23,7 +23,7 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode { self.addSubnode(self.textNode) } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState } diff --git a/submodules/TelegramUI/Sources/ChatSearchInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatSearchInputPanelNode.swift index 2b8150c7ea..b6988a7d8c 100644 --- a/submodules/TelegramUI/Sources/ChatSearchInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchInputPanelNode.swift @@ -28,7 +28,7 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode { private var needsSearchResultsTooltip = true - private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool)? + private var validLayout: (width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, metrics: LayoutMetrics, isSecondary: Bool, isMediaInputExpanded: Bool)? override var interfaceInteraction: ChatPanelInterfaceInteraction? { didSet { @@ -38,8 +38,8 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode { if let strongSelf = self, strongSelf.displayActivity != value { strongSelf.displayActivity = value strongSelf.activityIndicator.isHidden = !value - if let interfaceState = strongSelf.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics) + if let interfaceState = strongSelf.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: interfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) } } })) @@ -127,8 +127,8 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode { } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { - self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) if self.presentationInterfaceState != interfaceState { let themeUpdated = self.presentationInterfaceState?.theme !== interfaceState.theme diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index b5b3e34d4d..e9a78f14e5 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -198,7 +198,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe return entries } - let interaction = ChatListNodeInteraction(activateSearch: { + let interaction = ChatListNodeInteraction(context: context, activateSearch: { }, peerSelected: { _, _, _ in }, disabledPeerSelected: { _ in }, togglePeerSelected: { _ in @@ -398,7 +398,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceNode = self.sourceNode return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode.view, sourceNode.bounds) } else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift index b805b4dc1c..dd633334c6 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift @@ -132,7 +132,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { self.backdropNode.update(rect: rect, within: containerSize, transition: transition) } - func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) { + func updateLayout(size: CGSize, isMediaInputExpanded: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) { self.validLayout = size transition.updateFrame(layer: self.micButton.layer, frame: CGRect(origin: CGPoint(), size: size)) self.micButton.layoutItems() @@ -183,10 +183,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { } transition.updateFrame(node: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size)) - var expanded = false - if case let .media(_, maybeExpanded, _) = interfaceState.inputMode, maybeExpanded != nil { - expanded = true - } + let expanded = isMediaInputExpanded transition.updateSublayerTransformScale(node: self.expandMediaInputButton, scale: CGPoint(x: 1.0, y: expanded ? 1.0 : -1.0)) } diff --git a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 0c72039bfb..62327618b4 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift @@ -10,6 +10,8 @@ import AccountContext import ChatInterfaceState import AudioBlob import ChatPresentationInterfaceState +import ComponentFlow +import LottieAnimationComponent private let offsetThreshold: CGFloat = 10.0 private let dismissOffsetThreshold: CGFloat = 70.0 @@ -185,7 +187,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto private var modeTimeoutTimer: SwiftSignalKit.Timer? - private let innerIconView: UIImageView + private let animationView: ComponentView private var recordingOverlay: ChatTextInputAudioRecordingOverlay? private var startTouchLocation: CGPoint? @@ -288,7 +290,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) { self.theme = theme self.strings = strings - self.innerIconView = UIImageView() + self.animationView = ComponentView() self.presentController = presentController super.init(frame: CGRect()) @@ -297,8 +299,6 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto self.pallete = legacyInputMicPalette(from: theme) - self.insertSubview(self.innerIconView, at: 0) - self.disablesInteractiveTransitionGestureRecognizer = true self.updateMode(mode: self.mode, animated: false, force: true) @@ -318,51 +318,81 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto } private func updateMode(mode: ChatTextInputMediaRecordingButtonMode, animated: Bool, force: Bool) { + let previousMode = self.mode if mode != self.mode || force { self.mode = mode - - if animated { - let previousView = UIImageView(image: self.innerIconView.image) - previousView.frame = self.innerIconView.frame - self.addSubview(previousView) - previousView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) - previousView.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, removeOnCompletion: false, completion: { [weak previousView] _ in - previousView?.removeFromSuperview() - }) - } - - switch self.mode { - case .audio: - self.icon = PresentationResourcesChat.chatInputPanelVoiceActiveButtonImage(self.theme) - self.innerIconView.image = PresentationResourcesChat.chatInputPanelVoiceButtonImage(self.theme) - case .video: - self.icon = PresentationResourcesChat.chatInputPanelVideoActiveButtonImage(self.theme) - self.innerIconView.image = PresentationResourcesChat.chatInputPanelVideoButtonImage(self.theme) - } - if let image = self.innerIconView.image { - let size = self.bounds.size - let iconSize = image.size - self.innerIconView.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) - } - - if animated { - self.innerIconView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false) - self.innerIconView.layer.animateSpring(from: 0.4 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) + + self.updateAnimation(previousMode: previousMode) + } + } + + private func updateAnimation(previousMode: ChatTextInputMediaRecordingButtonMode) { + let image: UIImage? + switch self.mode { + case .audio: + self.icon = PresentationResourcesChat.chatInputPanelVoiceActiveButtonImage(self.theme) + image = PresentationResourcesChat.chatInputPanelVoiceButtonImage(self.theme) + case .video: + self.icon = PresentationResourcesChat.chatInputPanelVideoActiveButtonImage(self.theme) + image = PresentationResourcesChat.chatInputPanelVoiceButtonImage(self.theme) + } + + let size = self.bounds.size + let iconSize: CGSize + if let image = image { + iconSize = image.size + } else { + iconSize = size + } + + let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) + + let animationName: String + switch self.mode { + case .audio: + animationName = "anim_videoToMic" + case .video: + animationName = "anim_micToVideo" + } + + var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end) + if previousMode != mode { + animationMode = .animating(loop: false) + } + + let colorKeys = ["__allcolors__"] + var colors: [String: UIColor] = [:] + for colorKey in colorKeys { + colors[colorKey] = self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) + } + + let _ = animationView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: animationName, + mode: animationMode + ), + colors: colors, + size: animationFrame.size + )), + environment: {}, + containerSize: animationFrame.size + ) + + if let view = animationView.view { + view.isUserInteractionEnabled = false + if view.superview == nil { + self.insertSubview(view, at: 0) } + view.frame = animationFrame } } func updateTheme(theme: PresentationTheme) { self.theme = theme - switch self.mode { - case .audio: - self.icon = PresentationResourcesChat.chatInputPanelVoiceActiveButtonImage(self.theme) - self.innerIconView.image = PresentationResourcesChat.chatInputPanelVoiceButtonImage(self.theme) - case .video: - self.icon = PresentationResourcesChat.chatInputPanelVideoActiveButtonImage(self.theme) - self.innerIconView.image = PresentationResourcesChat.chatInputPanelVideoButtonImage(self.theme) - } + self.updateAnimation(previousMode: self.mode) self.pallete = legacyInputMicPalette(from: theme) self.micDecorationValue?.setColor(self.theme.chat.inputPanel.actionControlFillColor) @@ -467,8 +497,11 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto micDecoration.isHidden = false micDecoration.startAnimating() - innerIconView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) - innerIconView.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, removeOnCompletion: false) + let transition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) + if let layer = self.animationView.view?.layer { + transition.updateAlpha(layer: layer, alpha: 0.0) + transition.updateTransformScale(layer: layer, scale: 0.3) + } } override func animateOut(_ toSmallSize: Bool) { @@ -480,8 +513,11 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.03, delay: 0.15, removeOnCompletion: false) } else { micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false) - innerIconView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false) - innerIconView.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, removeOnCompletion: false) + let transition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut) + if let layer = self.animationView.view?.layer { + transition.updateAlpha(layer: layer, alpha: 1.0) + transition.updateTransformScale(layer: layer, scale: 1.0) + } } } @@ -490,8 +526,10 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto let size = self.bounds.size if size != self.previousSize { self.previousSize = size - let iconSize = self.innerIconView.bounds.size - self.innerIconView.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) + if let view = self.animationView.view { + let iconSize = view.bounds.size + view.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) + } } } } diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 06ddecf35f..f4a504d8eb 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -25,17 +25,27 @@ import ManagedAnimationNode import AttachmentUI import EditableChatTextNode import EmojiTextAttachmentView +import LottieAnimationComponent +import ComponentFlow private let accessoryButtonFont = Font.medium(14.0) private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers]) private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { - private let item: ChatTextInputAccessoryItem + private var item: ChatTextInputAccessoryItem + private var theme: PresentationTheme + private var strings: PresentationStrings private var width: CGFloat + private let iconImageNode: ASImageNode + private var animationView: ComponentView? private var imageEdgeInsets = UIEdgeInsets() init(item: ChatTextInputAccessoryItem, theme: PresentationTheme, strings: PresentationStrings) { self.item = item + self.theme = theme + self.strings = strings + + self.iconImageNode = ASImageNode() let (image, text, accessibilityLabel, alpha, insets) = AccessoryItemIconButtonNode.imageAndInsets(item: item, theme: theme, strings: strings) @@ -46,7 +56,16 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.isAccessibilityElement = true self.accessibilityTraits = [.button] - self.addSubnode(self.imageNode) + self.iconImageNode.isUserInteractionEnabled = false + self.addSubnode(self.iconImageNode) + + switch item { + case .input, .botInput, .silentPost: + self.iconImageNode.isHidden = true + self.animationView = ComponentView() + default: + break + } if let text = text { self.setAttributedTitle(NSAttributedString(string: text, font: accessoryButtonFont, textColor: theme.chat.inputPanel.inputControlColor), for: .normal) @@ -54,8 +73,8 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.setAttributedTitle(NSAttributedString(), for: .normal) } - self.imageNode.image = image - self.imageNode.alpha = alpha + self.iconImageNode.image = image + self.iconImageNode.alpha = alpha self.imageEdgeInsets = insets self.accessibilityLabel = accessibilityLabel @@ -65,15 +84,20 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { if highlighted { strongSelf.layer.removeAnimation(forKey: "opacity") strongSelf.alpha = 0.4 + strongSelf.layer.allowsGroupOpacity = true } else { strongSelf.alpha = 1.0 strongSelf.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + strongSelf.layer.allowsGroupOpacity = false } } } } func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) { + self.theme = theme + self.strings = strings + let (image, text, accessibilityLabel, alpha, insets) = AccessoryItemIconButtonNode.imageAndInsets(item: item, theme: theme, strings: strings) self.width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: text, strings: strings) @@ -84,9 +108,9 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.setAttributedTitle(NSAttributedString(), for: .normal) } - self.imageNode.image = image + self.iconImageNode.image = image self.imageEdgeInsets = insets - self.imageNode.alpha = alpha + self.iconImageNode.alpha = alpha self.accessibilityLabel = accessibilityLabel } @@ -95,14 +119,17 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { fatalError("init(coder:) has not been implemented") } - static func imageAndInsets(item: ChatTextInputAccessoryItem, theme: PresentationTheme, strings: PresentationStrings) -> (UIImage?, String?, String, CGFloat, UIEdgeInsets) { + private static func imageAndInsets(item: ChatTextInputAccessoryItem, theme: PresentationTheme, strings: PresentationStrings) -> (UIImage?, String?, String, CGFloat, UIEdgeInsets) { switch item { - case .keyboard: - return (PresentationResourcesChat.chatInputTextFieldKeyboardImage(theme), nil, strings.VoiceOver_Keyboard, 1.0, UIEdgeInsets()) - case let .stickers(enabled): - return (PresentationResourcesChat.chatInputTextFieldStickersImage(theme), nil, strings.VoiceOver_Stickers, enabled ? 1.0 : 0.4, UIEdgeInsets()) - case .inputButtons: - return (PresentationResourcesChat.chatInputTextFieldInputButtonsImage(theme), nil, strings.VoiceOver_BotKeyboard, 1.0, UIEdgeInsets()) + case let .input(isEnabled, inputMode), let .botInput(isEnabled, inputMode): + switch inputMode { + case .keyboard: + return (PresentationResourcesChat.chatInputTextFieldKeyboardImage(theme), nil, strings.VoiceOver_Keyboard, 1.0, UIEdgeInsets()) + case .stickers, .emoji: + return (PresentationResourcesChat.chatInputTextFieldStickersImage(theme), nil, strings.VoiceOver_Stickers, isEnabled ? 1.0 : 0.4, UIEdgeInsets()) + case .bot: + return (PresentationResourcesChat.chatInputTextFieldInputButtonsImage(theme), nil, strings.VoiceOver_BotKeyboard, 1.0, UIEdgeInsets()) + } case .commands: return (PresentationResourcesChat.chatInputTextFieldCommandsImage(theme), nil, strings.VoiceOver_BotCommands, 1.0, UIEdgeInsets()) case let .silentPost(value): @@ -122,25 +149,171 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } } - static func calculateWidth(item: ChatTextInputAccessoryItem, image: UIImage?, text: String?, strings: PresentationStrings) -> CGFloat { + private static func calculateWidth(item: ChatTextInputAccessoryItem, image: UIImage?, text: String?, strings: PresentationStrings) -> CGFloat { switch item { - case .keyboard, .stickers, .inputButtons, .silentPost, .commands, .scheduledMessages: - return (image?.size.width ?? 0.0) + CGFloat(8.0) - case let .messageAutoremoveTimeout(timeout): - var imageWidth = (image?.size.width ?? 0.0) + CGFloat(8.0) - if let _ = timeout, let text = text { - imageWidth = ceil((text as NSString).size(withAttributes: [.font: accessoryButtonFont]).width) + 10.0 - } - - return max(imageWidth, 24.0) + case .input, .botInput, .silentPost, .commands, .scheduledMessages: + return 32.0 + case let .messageAutoremoveTimeout(timeout): + var imageWidth = (image?.size.width ?? 0.0) + CGFloat(8.0) + if let _ = timeout, let text = text { + imageWidth = ceil((text as NSString).size(withAttributes: [.font: accessoryButtonFont]).width) + 10.0 + } + + return max(imageWidth, 24.0) } } - func updateLayout(size: CGSize) { - if let image = self.imageNode.image { + func updateLayout(item: ChatTextInputAccessoryItem, size: CGSize) { + let previousItem = self.item + self.item = item + + if let image = self.iconImageNode.image { + self.iconImageNode.image = AccessoryItemIconButtonNode.imageAndInsets(item: item, theme: self.theme, strings: self.strings).0 + let bottomInset: CGFloat = 0.0 let imageFrame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0) - bottomInset), size: image.size) - self.imageNode.frame = imageFrame + self.iconImageNode.frame = imageFrame + + if let animationView = self.animationView { + let width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: "", strings: self.strings) + let iconSize = CGSize(width: width, height: width) + + let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - width) / 2.0), y: floor((size.height - width) / 2.0) - bottomInset), size: CGSize(width: width, height: width)) + + var colorKeys: [String] = ["__allcolors__"] + let animationName: String + var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end) + + if case let .silentPost(muted) = item { + if case let .silentPost(previousMuted) = previousItem { + if muted { + animationName = "input_anim_channelMute" + } else { + animationName = "input_anim_channelUnmute" + } + if muted != previousMuted { + animationMode = .animating(loop: false) + } + } else { + animationName = "input_anim_channelMute" + } + } else { + var previousInputMode: ChatTextInputAccessoryItem.InputMode? + var inputMode: ChatTextInputAccessoryItem.InputMode? + + switch previousItem { + case let .input(_, itemInputMode), let .botInput(_, itemInputMode): + previousInputMode = itemInputMode + default: + break + } + switch item { + case let .input(_, itemInputMode), let .botInput(_, itemInputMode): + inputMode = itemInputMode + default: + break + } + + let emojiColorKeys = [ + "Ellipse 33.Ellipse 33.Stroke 1", + "Ellipse 34.Ellipse 34.Stroke 1", + "Oval.Oval.Fill 1", + "Oval 2.Oval.Fill 1", + "Path 85.Path 85.Stroke 1" + ] + + if let inputMode = inputMode { + switch inputMode { + case .keyboard: + if let previousInputMode = previousInputMode { + if case .stickers = previousInputMode { + animationName = "input_anim_stickerToKey" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "input_anim_smileToKey" + animationMode = .animating(loop: false) + } else if case .bot = previousInputMode { + animationName = "input_anim_botToKey" + animationMode = .animating(loop: false) + } else { + animationName = "input_anim_stickerToKey" + } + } else { + animationName = "input_anim_stickerToKey" + } + case .stickers: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "input_anim_keyToSticker" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "input_anim_smileToSticker" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "input_anim_keyToSticker" + } + } else { + animationName = "input_anim_keyToSticker" + } + case .emoji: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "input_anim_keyToSmile" + animationMode = .animating(loop: false) + } else if case .stickers = previousInputMode { + animationName = "input_anim_stickerToSmile" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "input_anim_keyToSmile" + } + } else { + animationName = "input_anim_keyToSmile" + } + case .bot: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "input_anim_keyToBot" + animationMode = .animating(loop: false) + } else { + animationName = "input_anim_keyToBot" + } + } else { + animationName = "input_anim_keyToBot" + } + } + } else { + animationName = "" + } + } + + var colors: [String: UIColor] = [:] + for colorKey in colorKeys { + colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) + } + + let animationSize = animationView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: animationName, + mode: animationMode + ), + colors: colors, + size: iconSize + )), + environment: {}, + containerSize: animationFrame.size + ) + if let view = animationView.view { + view.isUserInteractionEnabled = false + if view.superview == nil { + self.view.addSubview(view) + } + view.frame = CGRect(origin: CGPoint(x: animationFrame.minX + floor((animationFrame.width - animationSize.width) / 2.0), y: animationFrame.minY + floor((animationFrame.height - animationSize.height) / 2.0)), size: animationSize) + } + } } } @@ -177,7 +350,7 @@ private func calclulateTextFieldMinHeight(_ presentationInterfaceState: ChatPres return result } -private func calculateTextFieldRealInsets(_ presentationInterfaceState: ChatPresentationInterfaceState) -> UIEdgeInsets { +private func calculateTextFieldRealInsets(presentationInterfaceState: ChatPresentationInterfaceState, accessoryButtonsWidth: CGFloat) -> UIEdgeInsets { let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize) let top: CGFloat let bottom: CGFloat @@ -194,7 +367,11 @@ private func calculateTextFieldRealInsets(_ presentationInterfaceState: ChatPres top = 0.0 bottom = 0.0 } - return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: 0.0) + + var right: CGFloat = 0.0 + right += max(0.0, accessoryButtonsWidth - 14.0) + + return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: right) } private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, UIImage)? @@ -219,7 +396,7 @@ private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackground context.setBlendMode(.normal) context.setStrokeColor(strokeColor.cgColor) - let strokeWidth: CGFloat = 1.0 + let strokeWidth: CGFloat = UIScreenPixel context.setLineWidth(strokeWidth) context.strokeEllipse(in: CGRect(x: strokeWidth / 2.0, y: strokeWidth / 2.0, width: diameter - strokeWidth, height: diameter - strokeWidth)) })?.stretchableImage(withLeftCapWidth: Int(diameter) / 2, topCapHeight: Int(diameter) / 2) @@ -240,6 +417,68 @@ enum ChatTextInputPanelPasteData { case sticker(UIImage, Bool) } +final class CustomEmojiContainerView: UIView { + private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView? + + private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:] + + init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) { + self.emojiViewProvider = emojiViewProvider + + super.init(frame: CGRect()) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + func update(fontSize: CGFloat, emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)]) { + var nextIndexById: [Int64: Int] = [:] + + var validKeys = Set() + for (rect, emoji) in emojiRects { + let index: Int + if let nextIndex = nextIndexById[emoji.fileId] { + index = nextIndex + } else { + index = 0 + } + nextIndexById[emoji.fileId] = index + 1 + + let key = InlineStickerItemLayer.Key(id: emoji.fileId, index: index) + + let view: UIView + if let current = self.emojiLayers[key] { + view = current + } else if let newView = self.emojiViewProvider(emoji) { + view = newView + self.addSubview(newView) + self.emojiLayers[key] = view + } else { + continue + } + + let itemSize: CGFloat = floor(24.0 * fontSize / 17.0) + let size = CGSize(width: itemSize, height: itemSize) + + view.frame = CGRect(origin: CGPoint(x: floor(rect.midX - size.width / 2.0), y: floor(rect.midY - size.height / 2.0)), size: size) + + validKeys.insert(key) + } + + var removeKeys: [InlineStickerItemLayer.Key] = [] + for (key, view) in self.emojiLayers { + if !validKeys.contains(key) { + removeKeys.append(key) + view.removeFromSuperview() + } + } + for key in removeKeys { + self.emojiLayers.removeValue(forKey: key) + } + } +} + class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let clippingNode: ASDisplayNode var textPlaceholderNode: ImmediateTextNode @@ -249,6 +488,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let textInputContainer: ASDisplayNode var textInputNode: EditableTextNode? var dustNode: InvisibleInkDustNode? + var customEmojiContainerView: CustomEmojiContainerView? let textInputBackgroundNode: ASImageNode private var transparentTextInputBackgroundImage: UIImage? @@ -281,13 +521,15 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private var accessoryItemButtons: [(ChatTextInputAccessoryItem, AccessoryItemIconButtonNode)] = [] - private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool)? + private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool, Bool)? private var leftMenuInset: CGFloat = 0.0 var displayAttachmentMenu: () -> Void = { } var sendMessage: () -> Void = { } var paste: (ChatTextInputPanelPasteData) -> Void = { _ in } var updateHeight: (Bool) -> Void = { _ in } + var toggleExpandMediaInput: (() -> Void)? + var switchToTextInputIfNeeded: (() -> Void)? var updateActivity: () -> Void = { } @@ -360,13 +602,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } func updateInputTextState(_ state: ChatTextInputState, keepSendButtonEnabled: Bool, extendedSearchLayout: Bool, accessoryItems: [ChatTextInputAccessoryItem], animated: Bool) { - if state.inputText.length != 0 && self.textInputNode == nil { - self.loadTextInputNode() - } - - if let textInputNode = self.textInputNode, let currentState = self.presentationInterfaceState { - self.updatingInputState = true - + if let currentState = self.presentationInterfaceState { var updateAccessoryButtons = false if accessoryItems.count == self.accessoryItemButtons.count { for i in 0 ..< accessoryItems.count { @@ -384,8 +620,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { for item in accessoryItems { var itemAndButton: (ChatTextInputAccessoryItem, AccessoryItemIconButtonNode)? for i in 0 ..< self.accessoryItemButtons.count { - if self.accessoryItemButtons[i].0 == item { + if self.accessoryItemButtons[i].0.key == item.key { itemAndButton = self.accessoryItemButtons[i] + itemAndButton?.0 = item self.accessoryItemButtons.remove(at: i) break } @@ -402,6 +639,14 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } self.accessoryItemButtons = updatedButtons } + } + + if state.inputText.length != 0 && self.textInputNode == nil { + self.loadTextInputNode() + } + + if let textInputNode = self.textInputNode, let _ = self.presentationInterfaceState { + self.updatingInputState = true var textColor: UIColor = .black var accentTextColor: UIColor = .blue @@ -459,9 +704,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private var touchDownGestureRecognizer: TouchDownGestureRecognizer? - private var emojiViewProvider: ((String) -> UIView)? + var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? - init(presentationInterfaceState: ChatPresentationInterfaceState, presentationContext: ChatPresentationContext?, presentController: @escaping (ViewController) -> Void) { + init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, presentationContext: ChatPresentationContext?, presentController: @escaping (ViewController) -> Void) { self.presentationInterfaceState = presentationInterfaceState var hasSpoilers = true @@ -493,10 +738,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.menuButton.cornerRadius = 16.0 self.menuButton.accessibilityLabel = presentationInterfaceState.strings.Conversation_InputMenu self.menuButtonBackgroundNode = ASDisplayNode() + self.menuButtonBackgroundNode.isUserInteractionEnabled = false self.menuButtonClippingNode = ASDisplayNode() self.menuButtonClippingNode.clipsToBounds = true + self.menuButtonClippingNode.isUserInteractionEnabled = false self.menuButtonIconNode = MenuIconNode() + self.menuButtonIconNode.isUserInteractionEnabled = false self.menuButtonIconNode.customColor = presentationInterfaceState.theme.chat.inputPanel.actionControlForegroundColor self.menuButtonTextNode = ImmediateTextNode() @@ -522,6 +770,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { super.init() + self.context = context + self.addSubnode(self.clippingNode) self.sendAsAvatarContainerNode.activated = { [weak self] gesture, _ in @@ -565,7 +815,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } self.actionButtons.micButton.recordingDisabled = { [weak self] in - self?.interfaceInteraction?.displayRestrictedInfo(.mediaRecording, .tooltip) + if let strongSelf = self { + if strongSelf.presentationInterfaceState?.voiceMessagesAvailable == false { + self?.interfaceInteraction?.displayRestrictedInfo(.premiumVoiceMessages, .tooltip) + } else { + self?.interfaceInteraction?.displayRestrictedInfo(.mediaRecording, .tooltip) + } + } } self.actionButtons.micButton.beginRecording = { [weak self] in @@ -595,15 +851,15 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } self.actionButtons.micButton.offsetRecordingControls = { [weak self] in if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) } } } self.actionButtons.micButton.updateCancelTranslation = { [weak self] in if let strongSelf = self, let presentationInterfaceState = strongSelf.presentationInterfaceState { - if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) = strongSelf.validLayout { - let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics) + if let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = strongSelf.validLayout { + let _ = strongSelf.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) } } } @@ -664,18 +920,30 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { strongSelf.ensureFocused() } } + recognizer.waitForTouchUp = { [weak self] in + guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else { + return true + } + + if textInputNode.textView.isFirstResponder { + return true + } else { + return false + } + } self.textInputBackgroundNode.isUserInteractionEnabled = true self.textInputBackgroundNode.view.addGestureRecognizer(recognizer) - /*if let presentationContext = presentationContext { + if let presentationContext = presentationContext { self.emojiViewProvider = { [weak self, weak presentationContext] emoji in - guard let strongSelf = self, let presentationContext = presentationContext, let presentationInterfaceState = strongSelf.presentationInterfaceState, let context = strongSelf.context, let file = strongSelf.context?.animatedEmojiStickers[emoji]?.first?.file else { + guard let strongSelf = self, let presentationContext = presentationContext, let presentationInterfaceState = strongSelf.presentationInterfaceState, let context = strongSelf.context else { return UIView() } - return EmojiTextAttachmentView(context: context, file: file, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) + let pointSize = floor(24.0 * 1.3) + return EmojiTextAttachmentView(context: context, emoji: emoji, file: emoji.file, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12), pointSize: CGSize(width: pointSize, height: pointSize)) } - }*/ + } } required init?(coder aDecoder: NSCoder) { @@ -725,26 +993,26 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { textInputNode.view.disablesInteractiveTransitionGestureRecognizer = true self.textInputNode = textInputNode + var accessoryButtonsWidth: CGFloat = 0.0 + var firstButton = true + for (_, button) in self.accessoryItemButtons { + if firstButton { + firstButton = false + accessoryButtonsWidth += accessoryButtonInset + } else { + accessoryButtonsWidth += accessoryButtonSpacing + } + accessoryButtonsWidth += button.buttonWidth + } + if let presentationInterfaceState = self.presentationInterfaceState { refreshChatTextInputTypingAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize) - textInputNode.textContainerInset = calculateTextFieldRealInsets(presentationInterfaceState) + textInputNode.textContainerInset = calculateTextFieldRealInsets(presentationInterfaceState: presentationInterfaceState, accessoryButtonsWidth: accessoryButtonsWidth) } if !self.textInputContainer.bounds.size.width.isZero { let textInputFrame = self.textInputContainer.frame - var accessoryButtonsWidth: CGFloat = 0.0 - var firstButton = true - for (_, button) in self.accessoryItemButtons { - if firstButton { - firstButton = false - accessoryButtonsWidth += accessoryButtonInset - } else { - accessoryButtonsWidth += accessoryButtonSpacing - } - accessoryButtonsWidth += button.buttonWidth - } - textInputNode.frame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - self.textInputViewInternalInsets.bottom)) textInputNode.view.layoutIfNeeded() self.updateSpoiler() @@ -756,7 +1024,27 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let recognizer = TouchDownGestureRecognizer(target: self, action: #selector(self.textInputBackgroundViewTap(_:))) recognizer.touchDown = { [weak self] in if let strongSelf = self { - strongSelf.ensureFocused() + strongSelf.ensureFocusedOnTap() + } + } + recognizer.waitForTouchUp = { [weak self] in + guard let strongSelf = self, let textInputNode = strongSelf.textInputNode else { + return true + } + + if textInputNode.textView.isFirstResponder { + return true + } else if let (_, _, _, bottomInset, _, _, metrics, _, _) = strongSelf.validLayout { + let textFieldWaitsForTouchUp: Bool + if case .regular = metrics.widthClass, bottomInset.isZero { + textFieldWaitsForTouchUp = true + } else { + textFieldWaitsForTouchUp = false + } + + return textFieldWaitsForTouchUp + } else { + return false } } textInputNode.view.addGestureRecognizer(recognizer) @@ -845,18 +1133,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.actionButtons.updateAbsoluteRect(CGRect(origin: rect.origin.offsetBy(dx: self.actionButtons.frame.minX, dy: self.actionButtons.frame.minY), size: self.actionButtons.frame.size), within: containerSize, transition: transition) } } - - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { let previousAdditionalSideInsets = self.validLayout?.4 - self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary) - - let textFieldWaitsForTouchUp: Bool - if case .regular = metrics.widthClass, bottomInset.isZero { - textFieldWaitsForTouchUp = true - } else { - textFieldWaitsForTouchUp = false - } - self.touchDownGestureRecognizer?.waitForTouchUp = textFieldWaitsForTouchUp + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) var transition = transition var additionalOffset: CGFloat = 0.0 @@ -973,9 +1252,11 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize) if let textInputNode = self.textInputNode { - if let text = textInputNode.attributedText?.string { + if let text = textInputNode.attributedText { let range = textInputNode.selectedRange - textInputNode.attributedText = NSAttributedString(string: text, font: Font.regular(baseFontSize), textColor: textColor) + let updatedText = NSMutableAttributedString(attributedString: text) + updatedText.addAttribute(NSAttributedString.Key.foregroundColor, value: textColor, range: NSRange(location: 0, length: updatedText.length)) + textInputNode.attributedText = updatedText textInputNode.selectedRange = range } textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(baseFontSize), NSAttributedString.Key.foregroundColor.rawValue: textColor] @@ -1162,8 +1443,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { for item in interfaceState.inputTextPanelState.accessoryItems { var itemAndButton: (ChatTextInputAccessoryItem, AccessoryItemIconButtonNode)? for i in 0 ..< self.accessoryItemButtons.count { - if self.accessoryItemButtons[i].0 == item { + if self.accessoryItemButtons[i].0.key == item.key { itemAndButton = self.accessoryItemButtons[i] + itemAndButton?.0 = item self.accessoryItemButtons.remove(at: i) break } @@ -1595,7 +1877,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } if let presentationInterfaceState = self.presentationInterfaceState { - self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), transition: transition, interfaceState: presentationInterfaceState) + self.actionButtons.updateLayout(size: CGSize(width: 44.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, transition: transition, interfaceState: presentationInterfaceState) } if let _ = interfaceState.inputTextPanelState.mediaRecordingState { @@ -1647,7 +1929,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { var textInputViewRealInsets = UIEdgeInsets() if let presentationInterfaceState = self.presentationInterfaceState { - textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState) + textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState: presentationInterfaceState, accessoryButtonsWidth: accessoryButtonsWidth) } let textInputFrame = CGRect(x: leftInset + textFieldInsets.left, y: textFieldInsets.top, width: baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset, height: panelHeight - textFieldInsets.top - textFieldInsets.bottom) @@ -1656,6 +1938,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { transition.updateAlpha(node: self.textInputContainer, alpha: audioRecordingItemsAlpha) if let textInputNode = self.textInputNode { + textInputNode.textContainerInset = textInputViewRealInsets let textFieldFrame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - textInputViewInternalInsets.bottom)) let shouldUpdateLayout = textFieldFrame.size != textInputNode.frame.size transition.updateFrame(node: textInputNode, frame: textFieldFrame) @@ -1717,10 +2000,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.slowmodePlaceholderNode?.isHidden = true } - var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: minimalHeight - textFieldInsets.bottom - minimalInputHeight) - for (_, button) in self.accessoryItemButtons.reversed() { + var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: panelHeight - textFieldInsets.bottom - minimalInputHeight) + for (item, button) in self.accessoryItemButtons.reversed() { let buttonSize = CGSize(width: button.buttonWidth, height: minimalInputHeight) - button.updateLayout(size: buttonSize) + button.updateLayout(item: item, size: buttonSize) let buttonFrame = CGRect(origin: CGPoint(x: nextButtonTopRight.x - buttonSize.width, y: nextButtonTopRight.y + floor((minimalInputHeight - buttonSize.height) / 2.0)), size: buttonSize) if button.supernode == nil { self.clippingNode.addSubnode(button) @@ -1765,7 +2048,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } let mediaInputDisabled: Bool - if interfaceState.hasActiveGroupCall { + if !interfaceState.voiceMessagesAvailable { + mediaInputDisabled = true + } else if interfaceState.hasActiveGroupCall { mediaInputDisabled = true } else if let channel = interfaceState.renderedPeer?.peer as? TelegramChannel, channel.hasBannedPermission(.banSendMedia) != nil { mediaInputDisabled = true @@ -1774,7 +2059,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } else { mediaInputDisabled = false } - self.actionButtons.micButton.fadeDisabled = mediaInputDisabled + + var mediaInputIsActive = false + if case .media = interfaceState.inputMode { + mediaInputIsActive = true + } + + self.actionButtons.micButton.fadeDisabled = mediaInputDisabled || mediaInputIsActive self.updateActionButtons(hasText: inputHasText, hideMicButton: hideMicButton, animated: transition.isAnimated) @@ -1900,6 +2191,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor var rects: [CGRect] = [] + var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] + + let fontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize) if let attributedText = textInputNode.attributedText { let beginning = textInputNode.textView.beginningOfDocument @@ -1937,6 +2231,16 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { addSpoiler(startIndex: currentStartIndex, endIndex: endIndex) } } + + if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + if let start = textInputNode.textView.position(from: beginning, offset: range.location), let end = textInputNode.textView.position(from: start, offset: range.length), let textRange = textInputNode.textView.textRange(from: start, to: end) { + let textRects = textInputNode.textView.selectionRects(for: textRange) + for textRect in textRects { + customEmojiRects.append((textRect.rect, value)) + break + } + } + } }) } @@ -1957,6 +2261,28 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { dustNode.removeFromSupernode() self.dustNode = nil } + + if !customEmojiRects.isEmpty { + let customEmojiContainerView: CustomEmojiContainerView + if let current = self.customEmojiContainerView { + customEmojiContainerView = current + } else { + customEmojiContainerView = CustomEmojiContainerView(emojiViewProvider: { [weak self] emoji in + guard let strongSelf = self, let emojiViewProvider = strongSelf.emojiViewProvider else { + return nil + } + return emojiViewProvider(emoji) + }) + customEmojiContainerView.isUserInteractionEnabled = false + textInputNode.textView.addSubview(customEmojiContainerView) + self.customEmojiContainerView = customEmojiContainerView + } + + customEmojiContainerView.update(fontSize: fontSize, emojiRects: customEmojiRects) + } else if let customEmojiContainerView = self.customEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.customEmojiContainerView = nil + } } private func updateSpoilersRevealed(animated: Bool = true) { @@ -2056,7 +2382,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.counterTextNode.attributedText = NSAttributedString(string: "", font: counterFont, textColor: .black) } - if let (width, leftInset, rightInset, _, _, maxHeight, metrics, _) = self.validLayout { + if let (width, leftInset, rightInset, _, _, maxHeight, metrics, _, _) = self.validLayout { var composeButtonsOffset: CGFloat = 0.0 if self.extendedSearchLayout { composeButtonsOffset = 44.0 @@ -2196,6 +2522,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } + let hideExpandMediaInput = hideMicButton + if mediaInputIsActive { hideMicButton = true } @@ -2222,7 +2550,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } - if mediaInputIsActive { + if mediaInputIsActive && !hideExpandMediaInput { if self.actionButtons.expandMediaInputButton.alpha.isZero { self.actionButtons.expandMediaInputButton.alpha = 1.0 if animated { @@ -2247,7 +2575,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } private func updateTextHeight(animated: Bool) { - if let (width, leftInset, rightInset, _, additionalSideInsets, maxHeight, metrics, _) = self.validLayout { + if let (width, leftInset, rightInset, _, additionalSideInsets, maxHeight, metrics, _, _) = self.validLayout { let (_, textFieldHeight) = self.calculateTextFieldMetrics(width: width - leftInset - rightInset - additionalSideInsets.right - self.leftMenuInset, maxHeight: maxHeight, metrics: metrics) let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics) if !self.bounds.size.height.isEqual(to: panelHeight) { @@ -2320,9 +2648,23 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } @objc func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) { - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.text, state.keyboardButtonsMessage?.id) - }) + guard let interfaceInteraction = self.interfaceInteraction, let presentationInterfaceState = self.presentationInterfaceState else { + return + } + + switch presentationInterfaceState.inputMode { + case .text: + break + case .media: + break + case .inputButtons, .none: + if self.textInputNode?.textView.inputView == nil { + interfaceInteraction.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.text, state.keyboardButtonsMessage?.id) + }) + } + } + self.inputMenu.activate() } @@ -2330,9 +2672,22 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.storedInputLanguage = editableTextNode.textInputMode.primaryLanguage self.inputMenu.deactivate() - if let presentationInterfaceState = self.presentationInterfaceState, let peer = presentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil { - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in - return (.inputButtons, nil) + if let presentationInterfaceState = self.presentationInterfaceState { + if let peer = presentationInterfaceState.renderedPeer?.peer as? TelegramUser, peer.botInfo != nil, presentationInterfaceState.keyboardButtonsMessage != nil { + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in + return (.inputButtons, nil) + } + } else { + switch presentationInterfaceState.inputMode { + case .text: + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in + return (.none, nil) + } + case .media: + break + default: + break + } } } } @@ -2698,8 +3053,26 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.textInputNode?.becomeFirstResponder() } + func ensureFocusedOnTap() { + if self.textInputNode == nil { + self.loadTextInputNode() + } + + self.textInputNode?.becomeFirstResponder() + + self.switchToTextInputIfNeeded?() + } + + func backwardsDeleteText() { + guard let textInputNode = self.textInputNode else { + return + } + textInputNode.textView.deleteBackward() + } + @objc func expandButtonPressed() { - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + self.toggleExpandMediaInput?() + /*self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in if case let .media(mode, expanded, focused) = state.inputMode { if let _ = expanded { return (.media(mode: mode, expanded: nil, focused: focused), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) @@ -2709,37 +3082,40 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } else { return (state.inputMode, state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) } - }) + })*/ } @objc func accessoryItemButtonPressed(_ button: UIView) { for (item, currentButton) in self.accessoryItemButtons { if currentButton === button { switch item { - case let .stickers(enabled): - if enabled { - self.interfaceInteraction?.openStickers() - } else { - self.interfaceInteraction?.displayRestrictedInfo(.stickers, .tooltip) - } - case .keyboard: - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.text, state.keyboardButtonsMessage?.id) - }) - case .inputButtons: - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.inputButtons, nil) - }) - case .commands: - self.interfaceInteraction?.updateTextInputStateAndMode { _, inputMode in - return (ChatTextInputState(inputText: NSAttributedString(string: "/")), .text) - } - case .silentPost: - self.interfaceInteraction?.toggleSilentPost() - case .messageAutoremoveTimeout: - self.interfaceInteraction?.setupMessageAutoremoveTimeout() - case .scheduledMessages: - self.interfaceInteraction?.openScheduledMessages() + case let .input(isEnabled, inputMode), let .botInput(isEnabled, inputMode): + switch inputMode { + case .keyboard: + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.text, state.keyboardButtonsMessage?.id) + }) + case .stickers, .emoji: + if isEnabled { + self.interfaceInteraction?.openStickers() + } else { + self.interfaceInteraction?.displayRestrictedInfo(.stickers, .tooltip) + } + case .bot: + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.inputButtons, nil) + }) + } + case .commands: + self.interfaceInteraction?.updateTextInputStateAndMode { _, inputMode in + return (ChatTextInputState(inputText: NSAttributedString(string: "/")), .text) + } + case .silentPost: + self.interfaceInteraction?.toggleSilentPost() + case .messageAutoremoveTimeout: + self.interfaceInteraction?.setupMessageAutoremoveTimeout() + case .scheduledMessages: + self.interfaceInteraction?.openScheduledMessages() } break } @@ -2785,7 +3161,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { func frameForStickersButton() -> CGRect? { for (item, button) in self.accessoryItemButtons { - if case .stickers = item { + if case let .input(_, inputMode) = item, case .stickers = inputMode { return button.frame.insetBy(dx: 0.0, dy: 6.0) } } diff --git a/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift index 3ff6e5ddfe..c8eb3bbf8f 100644 --- a/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatUnblockInputPanelNode.swift @@ -82,7 +82,7 @@ final class ChatUnblockInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.unblockPeer() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/CommandChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/CommandChatInputContextPanelNode.swift index a3aa3b2f4e..8b9f2f0345 100644 --- a/submodules/TelegramUI/Sources/CommandChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/CommandChatInputContextPanelNode.swift @@ -63,7 +63,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { private var enqueuedTransitions: [(CommandChatInputContextPanelTransition, Bool)] = [] private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.listView = ListView() self.listView.isOpaque = false self.listView.stackFromBottom = true @@ -74,7 +74,7 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode { return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/CommandMenuChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/CommandMenuChatInputContextPanelNode.swift index c3d69c08db..de6d79d3bc 100644 --- a/submodules/TelegramUI/Sources/CommandMenuChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/CommandMenuChatInputContextPanelNode.swift @@ -66,7 +66,7 @@ final class CommandMenuChatInputContextPanelNode: ChatInputContextPanelNode { private let disposable = MetaDisposable() - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, peerId: PeerId) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, peerId: PeerId, chatPresentationContext: ChatPresentationContext) { self.listView = ListView() self.listView.clipsToBounds = false self.listView.isOpaque = false @@ -77,7 +77,7 @@ final class CommandMenuChatInputContextPanelNode: ChatInputContextPanelNode { return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift b/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift index ad0310c571..f5fbf51104 100644 --- a/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/DeleteChatInputPanelNode.swift @@ -35,7 +35,7 @@ final class DeleteChatInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.deleteChat() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/DisabledContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/DisabledContextResultsChatInputContextPanelNode.swift index c5e77562fe..8a558045eb 100644 --- a/submodules/TelegramUI/Sources/DisabledContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/DisabledContextResultsChatInputContextPanelNode.swift @@ -16,14 +16,14 @@ final class DisabledContextResultsChatInputContextPanelNode: ChatInputContextPan private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.containerNode = ASDisplayNode() self.separatorNode = ASDisplayNode() self.textNode = ImmediateTextNode() self.textNode.maximumNumberOfLines = 0 self.textNode.textAlignment = .center - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index dc168430ca..97ea2d7c5e 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -40,7 +40,7 @@ private struct DrawingPaneArrangement { private final class DrawingStickersScreenNode: ViewControllerTracingNode { private let context: AccountContext private var presentationData: PresentationData - fileprivate var selectSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + fileprivate var selectSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private var searchItemContext = StickerPaneSearchGlobalItemContext() private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings)> @@ -98,7 +98,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { fileprivate var dismiss: (() -> Void)? - init(context: AccountContext, selectSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?) { + init(context: AccountContext, selectSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) { self.context = context let presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = presentationData @@ -106,13 +106,13 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings)) - var selectStickerImpl: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + var selectStickerImpl: ((FileMediaReference, UIView, CGRect) -> Bool)? self.controllerInteraction = ChatControllerInteraction(openMessage: { _, _ in return false }, openPeer: { _, _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _, _ in }, openMessageReactionContextMenu: { _, _, _, _ in }, updateMessageReaction: { _, _ in }, activateMessagePinch: { _ in }, openMessageContextActions: { _, _, _, _ in }, navigateToMessage: { _, _ in }, navigateToMessageStandalone: { _ in - }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { fileReference, _, _, _, _, node, rect in return selectStickerImpl?(fileReference, node, rect) ?? false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in + }, tapMessage: nil, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { fileReference, _, _, _, _, node, rect, _ in return selectStickerImpl?(fileReference, node, rect) ?? false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in }, presentController: { _, _ in }, presentControllerInCurrent: { _, _ in }, navigationController: { @@ -143,7 +143,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in @@ -163,6 +163,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { }, openWebView: { _, _, _, _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { + }, dismissTextInput: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: true), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil)) @@ -236,7 +237,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -349,7 +350,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { sendSticker: { fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -1306,7 +1307,7 @@ final class DrawingStickersScreen: ViewController, TGPhotoPaintStickersScreen { public var screenWillDisappear: (() -> Void)? private let context: AccountContext - var selectSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + var selectSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private var controllerNode: DrawingStickersScreenNode { return self.displayNode as! DrawingStickersScreenNode @@ -1322,7 +1323,7 @@ final class DrawingStickersScreen: ViewController, TGPhotoPaintStickersScreen { return self._ready } - public init(context: AccountContext, selectSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil) { + public init(context: AccountContext, selectSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil) { self.context = context self.selectSticker = selectSticker @@ -1362,10 +1363,10 @@ final class DrawingStickersScreen: ViewController, TGPhotoPaintStickersScreen { override public func loadDisplayNode() { self.displayNode = DrawingStickersScreenNode( context: self.context, - selectSticker: { [weak self] file, sourceNode, sourceRect in + selectSticker: { [weak self] file, sourceView, sourceRect in if let strongSelf = self, let selectSticker = strongSelf.selectSticker { (strongSelf.displayNode as! DrawingStickersScreenNode).animateOut() - return selectSticker(file, sourceNode, sourceRect) + return selectSticker(file, sourceView, sourceRect) } else { return false } diff --git a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift index ff30790408..9c53911751 100644 --- a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift @@ -13,6 +13,10 @@ import RadialStatusNode import PhotoResources import TelegramStringFormatting import ChatPresentationInterfaceState +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer +import TextFormat final class EditAccessoryPanelNode: AccessoryPanelNode { let dateTimeFormat: PresentationDateTimeFormat @@ -22,7 +26,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { let lineNode: ASImageNode let iconNode: ASImageNode let titleNode: ImmediateTextNode - let textNode: ImmediateTextNode + let textNode: ImmediateTextNodeWithEntities let imageNode: TransformImageNode let dimNode: ASDisplayNode let drawIconNode: ASImageNode @@ -71,7 +75,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)? - init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat) { + init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { self.context = context self.messageId = messageId self.theme = theme @@ -99,10 +103,21 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { self.titleNode.maximumNumberOfLines = 1 self.titleNode.displaysAsynchronously = false - self.textNode = ImmediateTextNode() + self.textNode = ImmediateTextNodeWithEntities() self.textNode.maximumNumberOfLines = 1 self.textNode.displaysAsynchronously = false self.textNode.isUserInteractionEnabled = true + self.textNode.visibility = true + + if let animationCache = animationCache, let animationRenderer = animationRenderer { + self.textNode.arguments = TextNodeWithEntities.Arguments( + context: context, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false + ) + } self.imageNode = TransformImageNode() self.imageNode.contentAnimations = [.subsequentUpdates] @@ -170,7 +185,8 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { if let currentEditMediaReference = self.currentEditMediaReference { effectiveMessage = effectiveMessage.withUpdatedMedia([currentEditMediaReference.media]) } - (text, _, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(effectiveMessage), strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, dateTimeFormat: self.dateTimeFormat, accountPeerId: self.context.account.peerId) + let (attributedText, _, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(effectiveMessage), strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, dateTimeFormat: self.dateTimeFormat, accountPeerId: self.context.account.peerId) + text = attributedText.string } var updatedMediaReference: AnyMediaReference? @@ -237,6 +253,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { self.isPhoto = isPhoto let isMedia: Bool + let isText: Bool if let message = message { var effectiveMessage = message if let currentEditMediaReference = self.currentEditMediaReference { @@ -246,11 +263,14 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { switch messageContentKind(contentSettings: self.context.currentContentSettings.with { $0 }, message: EngineMessage(effectiveMessage), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: self.context.account.peerId) { case .text: isMedia = false + isText = true default: isMedia = true + isText = false } } else { isMedia = false + isText = true } let canEditMedia: Bool @@ -267,7 +287,29 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { titleString = self.strings.Conversation_EditingMessagePanelTitle } self.titleNode.attributedText = NSAttributedString(string: titleString, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor) - self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: isMedia ? self.theme.chat.inputPanel.secondaryTextColor : self.theme.chat.inputPanel.primaryTextColor) + + let textFont = Font.regular(14.0) + let messageText: NSAttributedString + if isText, let message = message { + let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in + switch entity.type { + case .Spoiler, .CustomEmoji: + return true + default: + return false + } + } + let textColor = self.theme.chat.inputPanel.primaryTextColor + if entities.count > 0 { + messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message) + } else { + messageText = NSAttributedString(string: text, font: textFont, textColor: isMedia ? self.theme.chat.inputPanel.secondaryTextColor : self.theme.chat.inputPanel.primaryTextColor) + } + } else { + messageText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: isMedia ? self.theme.chat.inputPanel.secondaryTextColor : self.theme.chat.inputPanel.primaryTextColor) + } + + self.textNode.attributedText = messageText let headerString: String = titleString self.actionArea.accessibilityLabel = "\(headerString).\n\(text)" @@ -324,8 +366,10 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { self.titleNode.attributedText = NSAttributedString(string: text, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor) } - if let text = self.textNode.attributedText?.string { - self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: self.theme.chat.inputPanel.primaryTextColor) + if let text = self.textNode.attributedText { + let mutableText = NSMutableAttributedString(attributedString: text) + mutableText.addAttribute(NSAttributedString.Key.foregroundColor, value: self.theme.chat.inputPanel.primaryTextColor, range: NSRange(location: 0, length: mutableText.length)) + self.textNode.attributedText = mutableText } if let (size, inset, interfaceState) = self.validLayout { diff --git a/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift index f9b39020be..c94ca1f172 100644 --- a/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/EmojisChatInputContextPanelNode.swift @@ -10,9 +10,13 @@ import MergeLists import AccountContext import Emoji import ChatPresentationInterfaceState +import AnimationCache +import MultiAnimationRenderer +import TextFormat -private struct EmojisChatInputContextPanelEntryStableId: Hashable, Equatable { - let symbol: String +private enum EmojisChatInputContextPanelEntryStableId: Hashable, Equatable { + case symbol(String) + case media(MediaId) } private func backgroundCenterImage(_ theme: PresentationTheme) -> UIImage? { @@ -55,25 +59,30 @@ private struct EmojisChatInputContextPanelEntry: Comparable, Identifiable { let theme: PresentationTheme let symbol: String let text: String + let file: TelegramMediaFile? var stableId: EmojisChatInputContextPanelEntryStableId { - return EmojisChatInputContextPanelEntryStableId(symbol: self.symbol) + if let file = self.file { + return .media(file.fileId) + } else { + return .symbol(self.symbol) + } } func withUpdatedTheme(_ theme: PresentationTheme) -> EmojisChatInputContextPanelEntry { - return EmojisChatInputContextPanelEntry(index: self.index, theme: theme, symbol: self.symbol, text: self.text) + return EmojisChatInputContextPanelEntry(index: self.index, theme: theme, symbol: self.symbol, text: self.text, file: self.file) } static func ==(lhs: EmojisChatInputContextPanelEntry, rhs: EmojisChatInputContextPanelEntry) -> Bool { - return lhs.index == rhs.index && lhs.symbol == rhs.symbol && lhs.text == rhs.text && lhs.theme === rhs.theme + return lhs.index == rhs.index && lhs.symbol == rhs.symbol && lhs.text == rhs.text && lhs.theme === rhs.theme && lhs.file?.fileId == rhs.file?.fileId } static func <(lhs: EmojisChatInputContextPanelEntry, rhs: EmojisChatInputContextPanelEntry) -> Bool { return lhs.index < rhs.index } - func item(account: Account, emojiSelected: @escaping (String) -> Void) -> ListViewItem { - return EmojisChatInputPanelItem(theme: self.theme, symbol: self.symbol, text: self.text, emojiSelected: emojiSelected) + func item(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, emojiSelected: @escaping (String, TelegramMediaFile?) -> Void) -> ListViewItem { + return EmojisChatInputPanelItem(context: context, theme: self.theme, symbol: self.symbol, text: self.text, file: self.file, animationCache: animationCache, animationRenderer: animationRenderer, emojiSelected: emojiSelected) } } @@ -83,12 +92,12 @@ private struct EmojisChatInputContextPanelTransition { let updates: [ListViewUpdateItem] } -private func preparedTransition(from fromEntries: [EmojisChatInputContextPanelEntry], to toEntries: [EmojisChatInputContextPanelEntry], account: Account, emojiSelected: @escaping (String) -> Void) -> EmojisChatInputContextPanelTransition { +private func preparedTransition(from fromEntries: [EmojisChatInputContextPanelEntry], to toEntries: [EmojisChatInputContextPanelEntry], context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, emojiSelected: @escaping (String, TelegramMediaFile?) -> Void) -> EmojisChatInputContextPanelTransition { let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries) let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) } - let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, emojiSelected: emojiSelected), directionHint: nil) } - let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, emojiSelected: emojiSelected), directionHint: nil) } + let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, animationCache: animationCache, animationRenderer: animationRenderer, emojiSelected: emojiSelected), directionHint: nil) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, animationCache: animationCache, animationRenderer: animationRenderer, emojiSelected: emojiSelected), directionHint: nil) } return EmojisChatInputContextPanelTransition(deletions: deletions, insertions: insertions, updates: updates) } @@ -106,7 +115,13 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode { private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? private var presentationInterfaceState: ChatPresentationInterfaceState? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + private let animationCache: AnimationCache + private let animationRenderer: MultiAnimationRenderer + + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { + self.animationCache = chatPresentationContext.animationCache + self.animationRenderer = chatPresentationContext.animationRenderer + self.backgroundNode = ASImageNode() self.backgroundNode.displayWithoutProcessing = true self.backgroundNode.displaysAsynchronously = false @@ -134,7 +149,7 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode { return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.placement = .overTextInput self.isOpaque = false @@ -147,12 +162,12 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode { self.clippingNode.addSubnode(self.listView) } - func updateResults(_ results: [(String, String)]) { + func updateResults(_ results: [(String, TelegramMediaFile?, String)]) { var entries: [EmojisChatInputContextPanelEntry] = [] var index = 0 var stableIds = Set() - for (symbol, text) in results { - let entry = EmojisChatInputContextPanelEntry(index: index, theme: self.theme, symbol: symbol.normalizedEmoji, text: text) + for (symbol, file, text) in results { + let entry = EmojisChatInputContextPanelEntry(index: index, theme: self.theme, symbol: symbol.normalizedEmoji, text: text, file: file) if stableIds.contains(entry.stableId) { continue } @@ -165,33 +180,54 @@ final class EmojisChatInputContextPanelNode: ChatInputContextPanelNode { private func prepareTransition(from: [EmojisChatInputContextPanelEntry]? , to: [EmojisChatInputContextPanelEntry]) { let firstTime = self.currentEntries == nil - let transition = preparedTransition(from: from ?? [], to: to, account: self.context.account, emojiSelected: { [weak self] text in - if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction { - interfaceInteraction.updateTextInputStateAndMode { textInputState, inputMode in - var hashtagQueryRange: NSRange? - inner: for (range, type, _) in textInputStateContextQueryRangeAndType(textInputState) { - if type == [.emojiSearch] { - var range = range - range.location -= 1 - range.length += 1 - hashtagQueryRange = range - break inner + let transition = preparedTransition(from: from ?? [], to: to, context: self.context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, emojiSelected: { [weak self] text, file in + guard let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction else { + return + } + + var text = text + + interfaceInteraction.updateTextInputStateAndMode { textInputState, inputMode in + var hashtagQueryRange: NSRange? + inner: for (range, type, _) in textInputStateContextQueryRangeAndType(textInputState) { + if type == [.emojiSearch] { + var range = range + range.location -= 1 + range.length += 1 + hashtagQueryRange = range + break inner + } + } + + if let range = hashtagQueryRange { + let inputText = NSMutableAttributedString(attributedString: textInputState.inputText) + + var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? + if let file = file { + loop: for attribute in file.attributes { + switch attribute { + case let .CustomEmoji(_, displayText, packReference): + text = displayText + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: file.fileId.id, file: file) + break loop + default: + break + } } } - if let range = hashtagQueryRange { - let inputText = NSMutableAttributedString(attributedString: textInputState.inputText) - - let replacementText = text - - inputText.replaceCharacters(in: range, with: replacementText) - - let selectionPosition = range.lowerBound + (replacementText as NSString).length - - return (ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition), inputMode) + var replacementText = NSAttributedString(string: text) + if let emojiAttribute = emojiAttribute { + replacementText = NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: emojiAttribute]) } - return (textInputState, inputMode) + + inputText.replaceCharacters(in: range, with: replacementText) + + let selectionPosition = range.lowerBound + (replacementText.string as NSString).length + + return (ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition), inputMode) } + return (textInputState, inputMode) } }) self.currentEntries = to diff --git a/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift b/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift index 7fdb8192a5..ea075f56ba 100644 --- a/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift +++ b/submodules/TelegramUI/Sources/EmojisChatInputPanelItem.swift @@ -6,19 +6,32 @@ import TelegramCore import SwiftSignalKit import Postbox import TelegramPresentationData +import AnimationCache +import MultiAnimationRenderer +import EmojiTextAttachmentView +import AccountContext +import TextFormat final class EmojisChatInputPanelItem: ListViewItem { + fileprivate let context: AccountContext fileprivate let theme: PresentationTheme fileprivate let symbol: String fileprivate let text: String - private let emojiSelected: (String) -> Void + fileprivate let file: TelegramMediaFile? + fileprivate let animationCache: AnimationCache + fileprivate let animationRenderer: MultiAnimationRenderer + private let emojiSelected: (String, TelegramMediaFile?) -> Void let selectable: Bool = true - public init(theme: PresentationTheme, symbol: String, text: String, emojiSelected: @escaping (String) -> Void) { + public init(context: AccountContext, theme: PresentationTheme, symbol: String, text: String, file: TelegramMediaFile?, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, emojiSelected: @escaping (String, TelegramMediaFile?) -> Void) { + self.context = context self.theme = theme self.symbol = symbol self.text = text + self.file = file + self.animationCache = animationCache + self.animationRenderer = animationRenderer self.emojiSelected = emojiSelected } @@ -70,7 +83,7 @@ final class EmojisChatInputPanelItem: ListViewItem { } func selected(listView: ListView) { - self.emojiSelected(self.symbol) + self.emojiSelected(self.symbol, self.file) } } @@ -79,6 +92,7 @@ private let textFont = Font.regular(32.0) final class EmojisChatInputPanelItemNode: ListViewItemNode { static let itemSize = CGSize(width: 45.0, height: 45.0) private let symbolNode: TextNode + private var emojiView: EmojiTextAttachmentView? init() { self.symbolNode = TextNode() @@ -111,6 +125,45 @@ final class EmojisChatInputPanelItemNode: ListViewItemNode { if let strongSelf = self { let _ = symbolApply() strongSelf.symbolNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((EmojisChatInputPanelItemNode.itemSize.width - symbolLayout.size.width) / 2.0), y: 0.0), size: symbolLayout.size) + + if let file = item.file { + strongSelf.symbolNode.isHidden = true + + let emojiView: EmojiTextAttachmentView + if let current = strongSelf.emojiView { + emojiView = current + } else { + emojiView = EmojiTextAttachmentView( + context: item.context, + emoji: ChatTextInputTextCustomEmojiAttribute( + stickerPack: nil, + fileId: file.fileId.id, + file: file + ), + file: file, + cache: item.animationCache, + renderer: item.animationRenderer, + placeholderColor: item.theme.list.mediaPlaceholderColor, + pointSize: CGSize(width: 40.0, height: 40.0) + ) + emojiView.layer.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0) + strongSelf.emojiView = emojiView + strongSelf.view.addSubview(emojiView) + + let emojiSize = CGSize(width: 40.0, height: 40.0) + let emojiFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((EmojisChatInputPanelItemNode.itemSize.width - emojiSize.width) / 2.0) + 1.0, y: floorToScreenPixels((EmojisChatInputPanelItemNode.itemSize.height - emojiSize.height) / 2.0)), size: emojiSize) + + emojiView.center = emojiFrame.center + emojiView.bounds = CGRect(origin: CGPoint(), size: emojiFrame.size) + } + } else { + strongSelf.symbolNode.isHidden = false + + if let emojiView = strongSelf.emojiView { + strongSelf.emojiView = nil + emojiView.removeFromSuperview() + } + } } }) } diff --git a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index 39986aa3ae..1938a1364a 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -10,6 +10,7 @@ import TelegramPresentationData import TelegramUIPreferences import MergeLists import StickerPackPreviewUI +import StickerPeekUI import OverlayStatusController import PresentationDataUtils import SearchBarNode @@ -192,7 +193,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { private let context: AccountContext private var presentationData: PresentationData private weak var controller: FeaturedStickersScreen? - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private var searchItemContext = StickerPaneSearchGlobalItemContext() let gridNode: GridNode @@ -222,7 +223,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } private var didSetReady: Bool = false - init(context: AccountContext, controller: FeaturedStickersScreen, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?) { + init(context: AccountContext, controller: FeaturedStickersScreen, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.controller = controller @@ -478,16 +479,16 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { if let item = item as? StickerPreviewPeekItem { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] menuItems = [ .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode, imageNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), imageNode.view, imageNode.bounds) } } f(.default) @@ -500,7 +501,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), with: nil) + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), with: nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -509,7 +510,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } else { text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -550,7 +551,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: item, menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: item, menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -570,13 +571,13 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { if let (itemNode, item) = itemNodeAndItem { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self { var menuItems: [ContextMenuItem] = [] menuItems = [ .action(ContextMenuActionItem(text: strongSelf.presentationData.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController, let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode, animationNode.bounds) + let _ = strongSelf.sendSticker?(.standalone(media: item.file), animationNode.view, animationNode.bounds) } f(.default) })), @@ -588,7 +589,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), with: nil) + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), with: nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -597,7 +598,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } else { text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -638,7 +639,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -651,10 +652,10 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { - let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: strongSelf.presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) strongSelf.peekController = controller strongSelf.controller?.presentInGlobalOverlay(controller) @@ -789,7 +790,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { final class FeaturedStickersScreen: ViewController { private let context: AccountContext fileprivate let highlightedPackId: ItemCollectionId? - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private var controllerNode: FeaturedStickersScreenNode { return self.displayNode as! FeaturedStickersScreenNode @@ -805,7 +806,7 @@ final class FeaturedStickersScreen: ViewController { fileprivate var searchNavigationNode: SearchNavigationContentNode? - public init(context: AccountContext, highlightedPackId: ItemCollectionId?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? = nil) { + public init(context: AccountContext, highlightedPackId: ItemCollectionId?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil) { self.context = context self.highlightedPackId = highlightedPackId self.sendSticker = sendSticker @@ -1034,7 +1035,7 @@ private enum FeaturedSearchEntry: Identifiable, Comparable { switch self { case let .sticker(_, code, stickerItem, theme): return StickerPaneSearchStickerItem(account: account, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in - interaction.sendSticker(.standalone(media: stickerItem.file), node, rect) + interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect) }) case let .global(_, info, topItems, installed, topSeparator): return StickerPaneSearchGlobalItem(account: account, theme: theme, strings: strings, listAppearance: true, fillsRow: true, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: { @@ -1080,7 +1081,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { private let inputNodeInteraction: ChatMediaInputNodeInteraction private var interaction: StickerPaneSearchInteraction? private weak var controller: FeaturedStickersScreen? - private let sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)? + private let sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? private let itemContext: StickerPaneSearchGlobalItemContext private var theme: PresentationTheme @@ -1115,7 +1116,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { } var isActiveUpdated: (() -> Void)? - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, inputNodeInteraction: ChatMediaInputNodeInteraction, controller: FeaturedStickersScreen, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, itemContext: StickerPaneSearchGlobalItemContext) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, inputNodeInteraction: ChatMediaInputNodeInteraction, controller: FeaturedStickersScreen, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, itemContext: StickerPaneSearchGlobalItemContext) { self.context = context self.inputNodeInteraction = inputNodeInteraction self.controller = controller @@ -1175,12 +1176,12 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { |> deliverOnMainQueue).start(next: { _ in }) } - }, sendSticker: { [weak self] file, sourceNode, sourceRect in + }, sendSticker: { [weak self] file, sourceView, sourceRect in if let strongSelf = self { - let _ = strongSelf.sendSticker?(file, sourceNode, sourceRect) + let _ = strongSelf.sendSticker?(file, sourceView, sourceRect) } }, getItemIsPreviewed: { item in - return inputNodeInteraction.previewedStickerPackItem == .pack(item) + return inputNodeInteraction.previewedStickerPackItem == .pack(item.file) }) self._ready.set(.single(Void())) @@ -1426,7 +1427,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { return (itemNode, StickerPreviewPeekItem.found(stickerItem)) } else if let itemNode = itemNode as? StickerPaneSearchGlobalItemNode { if let (node, item) = itemNode.itemAt(point: self.view.convert(point, to: itemNode.view)) { - return (node, StickerPreviewPeekItem.pack(item)) + return (node, StickerPreviewPeekItem.pack(item.file)) } } } diff --git a/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift index 4c6f222d5b..064cb6b28d 100644 --- a/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ForwardAccessoryPanelNode.swift @@ -15,67 +15,70 @@ import TextFormat import Markdown import TelegramNotices import ChatPresentationInterfaceState +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer -func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (String, Bool) { +func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (text: String, entities: [MessageTextEntity], isMedia: Bool) { for media in message.media { switch media { - case _ as TelegramMediaImage: - return (strings.Message_Photo, true) - case let file as TelegramMediaFile: - if file.isVideoSticker || file.isAnimatedSticker { - return (strings.Message_Sticker, true) - } - var fileName: String = strings.Message_File - for attribute in file.attributes { - switch attribute { - case .Sticker: - return (strings.Message_Sticker, true) - case let .FileName(name): - fileName = name - case let .Audio(isVoice, _, title, performer, _): - if isVoice { - return (strings.Message_Audio, true) - } else { - if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { - return (title + " — " + performer, true) - } else if let title = title, !title.isEmpty { - return (title, true) - } else if let performer = performer, !performer.isEmpty { - return (performer, true) - } else { - return (strings.Message_Audio, true) - } - } - case .Video: - if file.isAnimated { - return (strings.Message_Animation, true) - } else { - return (strings.Message_Video, true) - } - default: - break + case _ as TelegramMediaImage: + return (strings.Message_Photo, [], true) + case let file as TelegramMediaFile: + if file.isVideoSticker || file.isAnimatedSticker { + return (strings.Message_Sticker, [], true) + } + var fileName: String = strings.Message_File + for attribute in file.attributes { + switch attribute { + case .Sticker: + return (strings.Message_Sticker, [], true) + case let .FileName(name): + fileName = name + case let .Audio(isVoice, _, title, performer, _): + if isVoice { + return (strings.Message_Audio, [], true) + } else { + if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { + return (title + " — " + performer, [], true) + } else if let title = title, !title.isEmpty { + return (title, [], true) + } else if let performer = performer, !performer.isEmpty { + return (performer, [], true) + } else { + return (strings.Message_Audio, [], true) + } } + case .Video: + if file.isAnimated { + return (strings.Message_Animation, [], true) + } else { + return (strings.Message_Video, [], true) + } + default: + break } - return (fileName, true) - case _ as TelegramMediaContact: - return (strings.Message_Contact, true) - case let game as TelegramMediaGame: - return (game.title, true) - case _ as TelegramMediaMap: - return (strings.Message_Location, true) - case _ as TelegramMediaAction: - return ("", true) - case _ as TelegramMediaPoll: - return (strings.ForwardedPolls(1), true) - case let dice as TelegramMediaDice: - return (dice.emoji, true) - case let invoice as TelegramMediaInvoice: - return (invoice.title, true) - default: - break + } + return (fileName, [], true) + case _ as TelegramMediaContact: + return (strings.Message_Contact, [], true) + case let game as TelegramMediaGame: + return (game.title, [], true) + case _ as TelegramMediaMap: + return (strings.Message_Location, [], true) + case _ as TelegramMediaAction: + return ("", [], true) + case _ as TelegramMediaPoll: + return (strings.ForwardedPolls(1), [], true) + case let dice as TelegramMediaDice: + return (dice.emoji, [], true) + case let invoice as TelegramMediaInvoice: + return (invoice.title, [], true) + default: + break } } - return (message.text, false) + return (message.text, message.textEntitiesAttribute?.entities ?? [], false) } final class ForwardAccessoryPanelNode: AccessoryPanelNode { @@ -89,7 +92,8 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { let lineNode: ASImageNode let iconNode: ASImageNode let titleNode: ImmediateTextNode - let textNode: ImmediateTextNode + let textNode: ImmediateTextNodeWithEntities + private var originalText: NSAttributedString? private let actionArea: AccessibilityAreaNode @@ -102,7 +106,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)? - init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, nameDisplayOrder: PresentationPersonNameOrder, forwardOptionsState: ChatInterfaceForwardOptionsState?) { + init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, nameDisplayOrder: PresentationPersonNameOrder, forwardOptionsState: ChatInterfaceForwardOptionsState?, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { self.context = context self.messageIds = messageIds self.theme = theme @@ -131,7 +135,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { self.titleNode.maximumNumberOfLines = 1 self.titleNode.displaysAsynchronously = false - self.textNode = ImmediateTextNode() + self.textNode = ImmediateTextNodeWithEntities() self.textNode.maximumNumberOfLines = 1 self.textNode.displaysAsynchronously = false @@ -148,6 +152,16 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { self.addSubnode(self.textNode) self.addSubnode(self.actionArea) + if let animationCache = animationCache, let animationRenderer = animationRenderer { + self.textNode.arguments = TextNodeWithEntities.Arguments( + context: context, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false + ) + } + self.messageDisposable.set((context.account.postbox.messagesAtIds(messageIds) |> deliverOnMainQueue).start(next: { [weak self] messages in if let strongSelf = self { @@ -157,7 +171,7 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { var authors = "" var uniquePeerIds = Set() var title = "" - var text = "" + var text = NSMutableAttributedString(string: "") var sourcePeer: (Bool, String)? for message in messages { if let author = message.forwardInfo?.author ?? message.effectiveAuthor, !uniquePeerIds.contains(author.id) { @@ -178,11 +192,27 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { if messages.count == 1 { title = strongSelf.strings.Conversation_ForwardOptions_ForwardTitleSingle - let (string, _) = textStringForForwardedMessage(messages[0], strings: strings) - text = "\(authors): \(string)" + let (string, entities, _) = textStringForForwardedMessage(messages[0], strings: strings) + + text = NSMutableAttributedString(attributedString: NSAttributedString(string: "\(authors): ", font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)) + + let additionalText = NSMutableAttributedString(attributedString: NSAttributedString(string: string, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)) + for entity in entities { + switch entity.type { + case let .CustomEmoji(_, fileId): + let range = NSRange(location: entity.range.lowerBound, length: entity.range.upperBound - entity.range.lowerBound) + if range.lowerBound >= 0 && range.upperBound <= additionalText.length { + additionalText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: fileId, file: messages[0].associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) + } + default: + break + } + } + + text.append(additionalText) } else { title = strongSelf.strings.Conversation_ForwardOptions_ForwardTitle(Int32(messages.count)) - text = strongSelf.strings.Conversation_ForwardFrom(authors).string + text = NSMutableAttributedString(attributedString: NSAttributedString(string: strongSelf.strings.Conversation_ForwardFrom(authors).string, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)) } strongSelf.messages = messages @@ -190,7 +220,9 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { strongSelf.authors = authors strongSelf.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor) - strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor) + strongSelf.textNode.attributedText = text + strongSelf.originalText = text + strongSelf.textNode.visibility = true let headerString: String if messages.count == 1 { @@ -273,25 +305,21 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode { let filteredMessages = self.messages - var authors = self.authors ?? "" - if forwardOptionsState?.hideNames == true { - authors = self.strings.DialogList_You - } - var title = "" - var text = "" - if filteredMessages.count == 1, let message = filteredMessages.first { + if filteredMessages.count == 1 { title = self.strings.Conversation_ForwardOptions_ForwardTitleSingle - let (string, _) = textStringForForwardedMessage(message, strings: strings) - text = "\(authors): \(string)" } else { title = self.strings.Conversation_ForwardOptions_ForwardTitle(Int32(filteredMessages.count)) - text = self.strings.Conversation_ForwardFrom(authors).string } self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor) - self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: self.theme.chat.inputPanel.secondaryTextColor) + if let attributedText = self.textNode.attributedText { + let updatedText = NSMutableAttributedString(attributedString: attributedText) + updatedText.addAttribute(.foregroundColor, value: self.theme.chat.inputPanel.secondaryTextColor, range: NSRange(location: 0, length: updatedText.length)) + self.textNode.attributedText = updatedText + self.originalText = updatedText + } if let (size, inset, interfaceState) = self.validLayout { self.updateState(size: size, inset: inset, interfaceState: interfaceState) diff --git a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift index dc2993be47..845e95f258 100644 --- a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift @@ -331,9 +331,9 @@ final class GifPaneSearchContentNode: ASDisplayNode & PaneSearchContentNode { multiplexedNode.fileSelected = { [weak self] file, sourceNode, sourceRect in if let (collection, result) = file.contextResult { - let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, sourceRect, false) + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode.view, sourceRect, false) } else { - let _ = self?.controllerInteraction.sendGif(file.file, sourceNode, sourceRect, false, false) + let _ = self?.controllerInteraction.sendGif(file.file, sourceNode.view, sourceRect, false, false) } } diff --git a/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift index 93a48f9171..da5d7bc8a0 100644 --- a/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HashtagChatInputContextPanelNode.swift @@ -69,7 +69,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode { private var enqueuedTransitions: [(HashtagChatInputContextPanelTransition, Bool)] = [] private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.listView = ListView() self.listView.isOpaque = false self.listView.stackFromBottom = true @@ -80,7 +80,7 @@ final class HashtagChatInputContextPanelNode: ChatInputContextPanelNode { return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index 23a4da53d9..b229b974d7 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -10,6 +10,7 @@ import TelegramUIPreferences import MergeLists import AccountContext import StickerPackPreviewUI +import StickerPeekUI import ContextUI import ChatPresentationInterfaceState import UndoUI @@ -91,7 +92,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont private var enqueuedTransitions: [(HorizontalListContextResultsChatInputContextPanelTransition, Bool)] = [] private var hasValidLayout = false - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.strings = strings self.separatorNode = ASDisplayNode() @@ -108,7 +109,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true @@ -144,7 +145,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont return nil } - var selectedItemNodeAndContent: (ASDisplayNode, PeekControllerContent)? + var selectedItemNodeAndContent: (UIView, CGRect, PeekControllerContent)? strongSelf.listView.forEachItemNode { itemNode in if itemNode.frame.contains(convertedPoint), let itemNode = itemNode as? HorizontalListContextResultsChatInputPanelItemNode, let item = itemNode.item { if case let .internalReference(internalReference) = item.result, let file = internalReference.file, file.isSticker { @@ -162,9 +163,9 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont f(.default) if let strongSelf = self { - let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.interfaceInteraction?.getNavigationController(), sendSticker: { file, sourceNode, sourceRect in + let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.interfaceInteraction?.getNavigationController(), sendSticker: { file, sourceView, sourceRect in if let strongSelf = self { - return strongSelf.interfaceInteraction?.sendSticker(file, false, sourceNode, sourceRect) ?? false + return strongSelf.interfaceInteraction?.sendSticker(file, false, sourceView, sourceRect, nil) ?? false } else { return false } @@ -175,7 +176,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont } }))) } - selectedItemNodeAndContent = (itemNode, StickerPreviewPeekContent(account: item.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .found(FoundStickerItem(file: file, stringRepresentations: [])), menu: menuItems, openPremiumIntro: { [weak self] in + selectedItemNodeAndContent = (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: item.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .found(FoundStickerItem(file: file, stringRepresentations: [])), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -228,18 +229,18 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont f(.default) let _ = item.resultSelected(item.result, itemNode, itemNode.bounds) }))) - selectedItemNodeAndContent = (itemNode, ChatContextResultPeekContent(account: item.account, contextResult: item.result, menu: menuItems)) + selectedItemNodeAndContent = (itemNode.view, itemNode.bounds, ChatContextResultPeekContent(account: item.account, contextResult: item.result, menu: menuItems)) } } } return .single(selectedItemNodeAndContent) } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = PeekController(presentationData: presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) strongSelf.interfaceInteraction?.presentGlobalOverlayController(controller, nil) return controller diff --git a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift index 479356050c..5385b98998 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift @@ -17,11 +17,11 @@ final class HorizontalStickerGridItem: GridItem { let file: TelegramMediaFile let theme: PresentationTheme let isPreviewed: (HorizontalStickerGridItem) -> Bool - let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void + let sendSticker: (FileMediaReference, UIView, CGRect) -> Void let section: GridSection? = nil - init(account: Account, file: TelegramMediaFile, theme: PresentationTheme, isPreviewed: @escaping (HorizontalStickerGridItem) -> Bool, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void) { + init(account: Account, file: TelegramMediaFile, theme: PresentationTheme, isPreviewed: @escaping (HorizontalStickerGridItem) -> Bool, sendSticker: @escaping (FileMediaReference, UIView, CGRect) -> Void) { self.account = account self.file = file self.theme = theme @@ -54,7 +54,7 @@ final class HorizontalStickerGridItemNode: GridItemNode { private let stickerFetchedDisposable = MetaDisposable() - var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Void)? + var sendSticker: ((FileMediaReference, UIView, CGRect) -> Void)? private var currentIsPreviewing: Bool = false @@ -238,7 +238,7 @@ final class HorizontalStickerGridItemNode: GridItemNode { @objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) { if let (_, item, _) = self.currentState, case .ended = recognizer.state { - self.sendSticker?(.standalone(media: item.file), self, self.bounds) + self.sendSticker?(.standalone(media: item.file), self.view, self.bounds) } } diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 4cbfdca401..ae6925f588 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -10,13 +10,14 @@ import TelegramUIPreferences import MergeLists import AccountContext import StickerPackPreviewUI +import StickerPeekUI import ContextUI import ChatPresentationInterfaceState import PremiumUI import UndoUI final class HorizontalStickersChatContextPanelInteraction { - var previewedStickerItem: StickerPackItem? + var previewedStickerItem: TelegramMediaFile? } private func backgroundCenterImage(_ theme: PresentationTheme) -> UIImage? { @@ -72,7 +73,7 @@ private struct StickerEntry: Identifiable, Comparable { return HorizontalStickerGridItem(account: account, file: self.file, theme: theme, isPreviewed: { item in return false//stickersInteraction.previewedStickerItem == item }, sendSticker: { file, node, rect in - let _ = interfaceInteraction.sendSticker(file, true, node, rect) + let _ = interfaceInteraction.sendSticker(file, true, node, rect, nil) }) } } @@ -117,7 +118,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { private var stickerPreviewController: StickerPreviewController? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.strings = strings self.backgroundNode = ASImageNode() @@ -144,7 +145,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { self.stickersInteraction = HorizontalStickersChatContextPanelInteraction() - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.placement = .overTextInput self.isOpaque = false @@ -173,14 +174,14 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { if let itemNode = strongSelf.gridNode.itemNodeAtPoint(strongSelf.view.convert(point, to: strongSelf.gridNode.view)) as? HorizontalStickerGridItemNode, let item = itemNode.stickerItem { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { var menuItems: [ContextMenuItem] = [] menuItems = [ .action(ContextMenuActionItem(text: strongSelf.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode, itemNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil) })), .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) @@ -191,7 +192,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -200,7 +201,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -224,7 +225,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) } else { return false } @@ -241,7 +242,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -255,11 +256,11 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = PeekController(presentationData: presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) strongSelf.interfaceInteraction?.presentGlobalOverlayController(controller, nil) return controller @@ -267,11 +268,11 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { return nil }, updateContent: { [weak self] content in if let strongSelf = self { - var item: StickerPackItem? + var file: TelegramMediaFile? if let content = content as? StickerPreviewPeekContent, case let .pack(contentItem) = content.item { - item = contentItem + file = contentItem } - strongSelf.updatePreviewingItem(item: item, animated: true) + strongSelf.updatePreviewingItem(file: file, animated: true) } })) } @@ -366,9 +367,9 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { return super.hitTest(point, with: event) } - private func updatePreviewingItem(item: StickerPackItem?, animated: Bool) { - if self.stickersInteraction.previewedStickerItem != item { - self.stickersInteraction.previewedStickerItem = item + private func updatePreviewingItem(file: TelegramMediaFile?, animated: Bool) { + if self.stickersInteraction.previewedStickerItem?.fileId != file?.fileId { + self.stickersInteraction.previewedStickerItem = file self.gridNode.forEachItemNode { itemNode in if let itemNode = itemNode as? HorizontalStickerGridItemNode { diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 74f9b3eca9..986bd97fbf 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -9,6 +9,7 @@ import TelegramPresentationData import TelegramUIPreferences import AccountContext import StickerPackPreviewUI +import StickerPeekUI import ContextUI import ChatPresentationInterfaceState import PremiumUI @@ -42,10 +43,10 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie private weak var peekController: PeekController? - var previewedStickerItem: StickerPackItem? + var previewedStickerItem: TelegramMediaFile? var updateBackgroundOffset: ((CGFloat, Bool, ContainedViewLayoutTransition) -> Void)? - var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Void)? + var sendSticker: ((FileMediaReference, UIView, CGRect) -> Void)? var getControllerInteraction: (() -> ChatControllerInteraction?)? @@ -101,7 +102,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie if let itemNode = selectedNode, let item = itemNode.stickerItem { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() { var menuItems: [ContextMenuItem] = [] @@ -111,9 +112,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, animationNode, animationNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode, imageNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -125,9 +126,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, animationNode, animationNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, animationNode.view, animationNode.bounds, nil) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode, imageNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -143,7 +144,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -152,7 +153,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -179,7 +180,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) } else { return false } @@ -196,7 +197,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie } })) ) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self, let controllerInteraction = strongSelf.getControllerInteraction?() else { return } @@ -210,11 +211,11 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = PeekController(presentationData: presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) controller.visibilityUpdated = { [weak self] visible in self?.previewingStickersPromise.set(visible) @@ -226,18 +227,18 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie return nil }, updateContent: { [weak self] content in if let strongSelf = self { - var item: StickerPackItem? + var item: TelegramMediaFile? if let content = content as? StickerPreviewPeekContent, case let .pack(contentItem) = content.item { item = contentItem } - strongSelf.updatePreviewingItem(item: item, animated: true) + strongSelf.updatePreviewingItem(file: item, animated: true) } })) } - private func updatePreviewingItem(item: StickerPackItem?, animated: Bool) { - if self.previewedStickerItem != item { - self.previewedStickerItem = item + private func updatePreviewingItem(file: TelegramMediaFile?, animated: Bool) { + if self.previewedStickerItem?.fileId != file?.fileId { + self.previewedStickerItem = file for (_, itemNode) in self.itemNodes { itemNode.updatePreviewing(animated: animated) @@ -433,9 +434,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie file: item.file, theme: self.theme, isPreviewed: { [weak self] item in - return item.file.fileId == self?.previewedStickerItem?.file.fileId - }, sendSticker: { [weak self] file, node, rect in - self?.sendSticker?(file, node, rect) + return item.file.fileId == self?.previewedStickerItem?.fileId + }, sendSticker: { [weak self] file, view, rect in + self?.sendSticker?(file, view, rect) } ) itemNode = item.node(layout: GridNodeLayout( @@ -492,7 +493,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode { private var choosingStickerDisposable: Disposable? - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, peerId: PeerId?) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, peerId: PeerId?, chatPresentationContext: ChatPresentationContext) { self.containerNode = ASDisplayNode() self.backgroundNode = ASDisplayNode() @@ -535,7 +536,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode { self.stickersNode = InlineReactionSearchStickersNode(context: context, theme: theme, strings: strings, peerId: peerId) - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.placement = .overPanels self.isOpaque = false @@ -576,7 +577,7 @@ final class InlineReactionSearchPanel: ChatInputContextPanelNode { guard let strongSelf = self else { return } - let _ = strongSelf.controllerInteraction?.sendSticker(file, false, false, strongSelf.query, true, node, rect) + let _ = strongSelf.controllerInteraction?.sendSticker(file, false, false, strongSelf.query, true, node, rect, nil) } self.view.disablesInteractiveTransitionGestureRecognizer = true diff --git a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift index 6ae0117529..c08dd6594f 100644 --- a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift +++ b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift @@ -120,7 +120,7 @@ func legacyInputMicPalette(from theme: PresentationTheme) -> TGModernConversatio return TGModernConversationInputMicPallete(dark: theme.overallDarkAppearance, buttonColor: inputPanelTheme.actionControlFillColor, iconColor: inputPanelTheme.actionControlForegroundColor, backgroundColor: theme.rootController.navigationBar.opaqueBackgroundColor, borderColor: inputPanelTheme.panelSeparatorColor, lock: inputPanelTheme.panelControlAccentColor, textColor: inputPanelTheme.primaryTextColor, secondaryTextColor: inputPanelTheme.secondaryTextColor, recording: inputPanelTheme.mediaRecordingDotColor) } -func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, context: AccountContext, peerId: PeerId, slowmodeState: ChatSlowmodeState?, hasSchedule: Bool, send: @escaping (InstantVideoController, EnqueueMessage?) -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) -> InstantVideoController { +func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, context: AccountContext, peerId: PeerId, slowmodeState: ChatSlowmodeState?, hasSchedule: Bool, send: @escaping (InstantVideoController, EnqueueMessage?) -> Void, displaySlowmodeTooltip: @escaping (UIView, CGRect) -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) -> InstantVideoController { let isSecretChat = peerId.namespace == Namespaces.Peer.SecretChat let legacyController = InstantVideoController(presentation: .custom, theme: theme) @@ -212,7 +212,7 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, } let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.FileName(fileName: "video.mp4"), .Video(duration: Int(finalDuration), size: PixelDimensions(finalDimensions), flags: [.instantRoundVideo])]) - var message: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + var message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) let scheduleTime: Int32? = scheduleTimestamp > 0 ? scheduleTimestamp : nil @@ -244,7 +244,7 @@ func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, controller.displaySlowmodeTooltip = { [weak legacyController, weak controller] in if let legacyController = legacyController, let controller = controller { let rect = controller.frameForSendButton() - displaySlowmodeTooltip(legacyController.displayNode, rect) + displaySlowmodeTooltip(legacyController.displayNode.view, rect) } } legacyController.bindCaptureController(controller) diff --git a/submodules/TelegramUI/Sources/MentionChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/MentionChatInputContextPanelNode.swift index 8705221cdc..2c78873718 100644 --- a/submodules/TelegramUI/Sources/MentionChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/MentionChatInputContextPanelNode.swift @@ -67,7 +67,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode { private var enqueuedTransitions: [(CommandChatInputContextPanelTransition, Bool)] = [] private var validLayout: (CGSize, CGFloat, CGFloat, CGFloat)? - init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, mode: MentionChatInputContextPanelMode) { + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, mode: MentionChatInputContextPanelMode, chatPresentationContext: ChatPresentationContext) { self.mode = mode self.listView = ListView() @@ -80,7 +80,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode { return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/NotificationContentContext.swift b/submodules/TelegramUI/Sources/NotificationContentContext.swift index a74a244e63..035a2cf1cf 100644 --- a/submodules/TelegramUI/Sources/NotificationContentContext.swift +++ b/submodules/TelegramUI/Sources/NotificationContentContext.swift @@ -138,7 +138,7 @@ public final class NotificationViewControllerImpl { return nil }) - sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), resolvedDeviceName: nil), premiumProductId: nil, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) + sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), resolvedDeviceName: nil), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) presentationDataPromise.set(sharedAccountContext!.presentationData) } diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index dd1db1ddce..09118aa5dc 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -66,7 +66,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { params.dismissInput() let controllerParams = LocationViewParams(sendLiveLocation: { location in - let outMessage: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) + let outMessage: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil) params.enqueueMessage(outMessage) }, stopLiveLocation: { messageId in params.context.liveLocationManager?.cancelLiveLocation(peerId: messageId?.peerId ?? params.message.id.peerId) @@ -78,29 +78,40 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool { params.navigationController?.pushViewController(controller) return true case let .stickerPack(reference): - let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { info, items, action in + let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { actions in let presentationData = params.context.sharedContext.currentPresentationData.with { $0 } - var animateInAsReplacement = false - if let navigationController = params.navigationController { - for controller in navigationController.overlayControllers { - if let controller = controller as? UndoOverlayController { - controller.dismissWithCommitActionAndReplacementAnimation() - animateInAsReplacement = true + + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + })) + } + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + + var animateInAsReplacement = false + if let navigationController = params.navigationController { + for controller in navigationController.overlayControllers { + if let controller = controller as? UndoOverlayController { + controller.dismissWithCommitActionAndReplacementAnimation() + animateInAsReplacement = true + } } } - } - switch action { - case .add: - params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in - return true - })) - case let .remove(positionInList): - params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in - if case .undo = action { - let _ = params.context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() - } - return true - })) + switch action { + case .add: + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { _ in + return true + })) + case let .remove(positionInList): + params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: params.context), elevatedLayout: true, animateInAsReplacement: animateInAsReplacement, action: { action in + if case .undo = action { + let _ = params.context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() + } + return true + })) + } } }) params.dismissInput() diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 490c7bc021..a945582f78 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -45,7 +45,7 @@ private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatContr } } -func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)? = nil, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) { +func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)? = nil, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) { let updatedPresentationData: (initial: PresentationData, signal: Signal)? if case let .chat(_, maybeUpdatedPresentationData) = urlContext { updatedPresentationData = maybeUpdatedPresentationData @@ -163,60 +163,35 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur present(c, a) }, messageId: replyThreadMessage.messageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).start() } - case let .stickerPack(name): + case let .stickerPack(name, _): dismissInput() - /*if false { - var mainStickerPack: StickerPackReference? - var stickerPacks: [StickerPackReference] = [] - if let message = contentContext as? Message { - let dataDetector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType([.link]).rawValue) - if let matches = dataDetector?.matches(in: message.text, options: [], range: NSRange(message.text.startIndex ..< message.text.endIndex, in: message.text)) { - for match in matches { - guard let stringRange = Range(match.range, in: message.text) else { - continue - } - let urlText = String(message.text[stringRange]) - if let resultName = parseStickerPackUrl(urlText) { - stickerPacks.append(.name(resultName)) - if resultName == name { - mainStickerPack = .name(resultName) - } - } - } - if mainStickerPack == nil { - mainStickerPack = .name(name) - stickerPacks.insert(.name(name), at: 0) - } - } else { - mainStickerPack = .name(name) - stickerPacks = [.name(name)] + + let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { actions in + if actions.count > 1, let first = actions.first { + if case .add = first.2 { + present(UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), cancel: ""), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + return true + }), nil) } - } else { - mainStickerPack = .name(name) - stickerPacks = [.name(name)] - } - if let mainStickerPack = mainStickerPack, !stickerPacks.isEmpty { - let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, parentNavigationController: navigationController, sendSticker: sendSticker) - present(controller, nil) - } - } else {*/ - let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { info, items, action in + } else if let (info, items, action) = actions.first { + let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks + switch action { case .add: - present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in + present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return true }), nil) case let .remove(positionInList): - present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_RemovedTitle, text: presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in + present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in if case .undo = action { let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start() } return true }), nil) } - }) + } + }) present(controller, nil) - //} case let .instantView(webpage, anchor): navigationController?.pushViewController(InstantPageController(context: context, webPage: webpage, sourcePeerType: .channel, anchor: anchor)) case let .join(link): diff --git a/submodules/TelegramUI/Sources/OpenUrl.swift b/submodules/TelegramUI/Sources/OpenUrl.swift index c81e1bfe17..29e075649e 100644 --- a/submodules/TelegramUI/Sources/OpenUrl.swift +++ b/submodules/TelegramUI/Sources/OpenUrl.swift @@ -295,6 +295,22 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur convertedUrl = "https://t.me/addstickers/\(set)" } } + } else if parsedUrl.host == "addemoji" { + if let components = URLComponents(string: "/?" + query) { + var set: String? + if let queryItems = components.queryItems { + for queryItem in queryItems { + if let value = queryItem.value { + if queryItem.name == "set" { + set = value + } + } + } + } + if let set = set { + convertedUrl = "https://t.me/addemoji/\(set)" + } + } } else if parsedUrl.host == "invoice" { if let components = URLComponents(string: "/?" + query) { var slug: String? diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 2029e31d4c..928371d929 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -80,7 +80,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in - }, sendSticker: { _, _, _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false @@ -135,7 +135,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in @@ -155,6 +155,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, openWebView: { _, _, _, _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { + }, dismissTextInput: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil)) self.dimNode = ASDisplayNode() diff --git a/submodules/TelegramUI/Sources/OwnershipTransferController.swift b/submodules/TelegramUI/Sources/OwnershipTransferController.swift index 109fd3f2d9..d3c52855bc 100644 --- a/submodules/TelegramUI/Sources/OwnershipTransferController.swift +++ b/submodules/TelegramUI/Sources/OwnershipTransferController.swift @@ -38,7 +38,7 @@ private func commitOwnershipTransferController(context: AccountContext, updatedP controller?.theme = AlertControllerTheme(presentationData: presentationData) contentNode?.theme = presentationData.theme }) - controller.dismissed = { + controller.dismissed = { _ in presentationDataDisposable.dispose() disposable.dispose() } diff --git a/submodules/TelegramUI/Sources/PaneSearchContainerNode.swift b/submodules/TelegramUI/Sources/PaneSearchContainerNode.swift index d00c0d977c..13244d5c08 100644 --- a/submodules/TelegramUI/Sources/PaneSearchContainerNode.swift +++ b/submodules/TelegramUI/Sources/PaneSearchContainerNode.swift @@ -8,6 +8,7 @@ import TelegramCore import TelegramPresentationData import AccountContext import ChatPresentationInterfaceState +import EntityKeyboard private let searchBarHeight: CGFloat = 52.0 @@ -27,7 +28,7 @@ protocol PaneSearchContentNode { func itemAt(point: CGPoint) -> (ASDisplayNode, Any)? } -final class PaneSearchContainerNode: ASDisplayNode { +final class PaneSearchContainerNode: ASDisplayNode, EntitySearchContainerNode { private let context: AccountContext private let mode: ChatMediaInputSearchMode public private(set) var contentNode: PaneSearchContentNode & ASDisplayNode @@ -39,6 +40,8 @@ final class PaneSearchContainerNode: ASDisplayNode { private var validLayout: CGSize? + var onCancel: (() -> Void)? + var openGifContextMenu: ((MultiplexedVideoNodeFile, ASDisplayNode, CGRect, ContextGesture, Bool) -> Void)? var ready: Signal { @@ -75,8 +78,11 @@ final class PaneSearchContainerNode: ASDisplayNode { self?.searchBar.activity = active } - self.searchBar.cancel = { + self.searchBar.cancel = { [weak self] in cancel() + + self?.searchBar.view.endEditing(true) + self?.onCancel?() } self.searchBar.activate() diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift index ec7e6e3ecf..fdd8ed624e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -334,7 +334,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { let titleFixedFont = Font.monospace(fontSize) let entities = generateTextEntities(text, enabledTypes: enabledEntities) - return stringWithAppliedEntities(text, entities: entities, baseColor: textColorValue, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont) + return stringWithAppliedEntities(text, entities: entities, baseColor: textColorValue, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont, message: nil) } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift index 2878a8e50b..c8ca92ec23 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift @@ -1254,7 +1254,8 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme media: [fakeFile], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) let messageItem = ListMessageItem( presentationData: self.chatPresentationData, @@ -2433,7 +2434,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro media: [fakeFile], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), - associatedMessageIds: [] + associatedMessageIds: [], + associatedMedia: [:] ) let messageItem = ListMessageItem( presentationData: self.itemGridBinding.chatPresentationData, diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index c5ffeae642..0653983289 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -310,7 +310,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -359,6 +359,8 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { displayCopyProtectionTip(node, save) }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) @@ -377,7 +379,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: self.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil) - let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics) + let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics, isMediaInputExpanded: false) transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeight))) @@ -2209,7 +2211,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) }, sendCurrentMessage: { _ in }, sendMessage: { _ in - }, sendSticker: { _, _, _, _, _, _, _ in + }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false @@ -2334,7 +2336,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in @@ -2354,6 +2356,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }, openWebView: { _, _, _, _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { + }, dismissTextInput: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil)) self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in @@ -3362,8 +3365,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate transitionCompletion() }, presentStickers: { [weak self] completion in if let strongSelf = self { - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in - completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in + completion(fileReference.media, fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.controller?.present(controller, in: .window(.root)) @@ -3879,11 +3882,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate let filteredButtons = allHeaderButtons.subtracting(headerButtons) - var canChangeColors = false - if let peer = peer as? TelegramUser, peer.botInfo == nil && strongSelf.data?.encryptionKeyFingerprint == nil { - canChangeColors = true - } - var currentAutoremoveTimeout: Int32? if let cachedData = data.cachedData as? CachedUserData { switch cachedData.autoremoveTimeout { @@ -3930,77 +3928,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate canSetupAutoremoveTimeout = true } } - - if canSetupAutoremoveTimeout { - let strings = strongSelf.presentationData.strings - items.append(.action(ContextMenuActionItem(text: currentAutoremoveTimeout == nil ? strongSelf.presentationData.strings.PeerInfo_EnableAutoDelete : strongSelf.presentationData.strings.PeerInfo_AdjustAutoDelete, icon: { theme in - if let currentAutoremoveTimeout = currentAutoremoveTimeout { - let text = NSAttributedString(string: shortTimeIntervalString(strings: strings, value: currentAutoremoveTimeout), font: Font.regular(14.0), textColor: theme.contextMenu.primaryColor) - let bounds = text.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil) - return generateImage(bounds.size.integralFloor, rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - UIGraphicsPushContext(context) - text.draw(in: bounds) - UIGraphicsPopContext() - }) - } else { - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor) - } - }, action: { [weak self] c, _ in - var subItems: [ContextMenuItem] = [] - - subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in - c.popItems() - }))) - subItems.append(.separator) - - let presetValues: [Int32] = [ - 1 * 24 * 60 * 60, - 7 * 24 * 60 * 60, - 31 * 24 * 60 * 60 - ] - - for value in presetValues { - subItems.append(.action(ContextMenuActionItem(text: timeIntervalString(strings: strings, value: value), icon: { _ in - return nil - }, action: { _, f in - f(.default) - - self?.setAutoremove(timeInterval: value) - }))) - } - - subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteSettingOther, icon: { _ in - return nil - }, action: { _, f in - f(.default) - self?.openAutoremove(currentValue: currentAutoremoveTimeout) - }))) - - if let _ = currentAutoremoveTimeout { - subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteDisable, textColor: .destructive, icon: { _ in - return nil - }, action: { _, f in - f(.default) - - self?.setAutoremove(timeInterval: nil) - }))) - } - - subItems.append(.separator) - - subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteInfo, textLayout: .multiline, textFont: .small, icon: { _ in - return nil - }, action: nil as ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void) -> Void)?))) - - c.pushItems(items: .single(ContextController.Items(content: .list(subItems)))) - }))) - items.append(.separator) - } - if filteredButtons.contains(.call) { items.append(.action(ContextMenuActionItem(text: presentationData.strings.PeerInfo_ButtonCall, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Call"), color: theme.contextMenu.primaryColor) @@ -4019,6 +3947,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } if let user = peer as? TelegramUser { + if user.botInfo == nil && strongSelf.data?.encryptionKeyFingerprint == nil { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeColors, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + + self?.openChatForThemeChange() + }))) + } + if let _ = user.botInfo { if user.username != nil { items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ShareBot, icon: { theme in @@ -4057,6 +3995,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } } + if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_StartSecretChat, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Lock"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + + self?.openStartSecretChat() + }))) + } + if user.botInfo == nil && data.isContact { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Profile_ShareContactButton, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) @@ -4112,23 +4060,87 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } - if canChangeColors { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_ChangeColors, icon: { theme in - generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ApplyTheme"), color: theme.contextMenu.primaryColor) - }, action: { _, f in + if !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport), let cachedData = data.cachedData as? CachedUserData, !cachedData.premiumGiftOptions.isEmpty { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.PeerInfo_GiftPremium, icon: { theme in + generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Gift"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in f(.dismissWithoutContent) - self?.openChatForThemeChange() + if let strongSelf = self { + let controller = PremiumGiftScreen(context: strongSelf.context, peerId: strongSelf.peerId, options: cachedData.premiumGiftOptions) + strongSelf.controller?.push(controller) + } }))) } - - if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser && user.botInfo == nil && !user.flags.contains(.isSupport) { - items.append(.action(ContextMenuActionItem(text: presentationData.strings.UserInfo_StartSecretChat, icon: { theme in - generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Lock"), color: theme.contextMenu.primaryColor) - }, action: { _, f in - f(.dismissWithoutContent) + + let itemsCount = items.count + + if canSetupAutoremoveTimeout { + let strings = strongSelf.presentationData.strings + items.append(.action(ContextMenuActionItem(text: currentAutoremoveTimeout == nil ? strongSelf.presentationData.strings.PeerInfo_EnableAutoDelete : strongSelf.presentationData.strings.PeerInfo_AdjustAutoDelete, icon: { theme in + if let currentAutoremoveTimeout = currentAutoremoveTimeout { + let text = NSAttributedString(string: shortTimeIntervalString(strings: strings, value: currentAutoremoveTimeout), font: Font.regular(14.0), textColor: theme.contextMenu.primaryColor) + let bounds = text.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + return generateImage(bounds.size.integralFloor, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + UIGraphicsPushContext(context) + text.draw(in: bounds) + UIGraphicsPopContext() + }) + } else { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor) + } + }, action: { [weak self] c, _ in + var subItems: [ContextMenuItem] = [] - self?.openStartSecretChat() + subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) + }, action: { c, _ in + c.popItems() + }))) + subItems.append(.separator) + + let presetValues: [Int32] = [ + 1 * 24 * 60 * 60, + 7 * 24 * 60 * 60, + 31 * 24 * 60 * 60 + ] + + for value in presetValues { + subItems.append(.action(ContextMenuActionItem(text: timeIntervalString(strings: strings, value: value), icon: { _ in + return nil + }, action: { _, f in + f(.default) + + self?.setAutoremove(timeInterval: value) + }))) + } + + subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteSettingOther, icon: { _ in + return nil + }, action: { _, f in + f(.default) + + self?.openAutoremove(currentValue: currentAutoremoveTimeout) + }))) + + if let _ = currentAutoremoveTimeout { + subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteDisable, textColor: .destructive, icon: { _ in + return nil + }, action: { _, f in + f(.default) + + self?.setAutoremove(timeInterval: nil) + }))) + } + + subItems.append(.separator) + + subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteInfo, textLayout: .multiline, textFont: .small, icon: { _ in + return nil + }, action: nil as ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void) -> Void)?))) + + c.pushItems(items: .single(ContextController.Items(content: .list(subItems)))) }))) } @@ -4168,6 +4180,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } } + + let finalItemsCount = items.count + + if finalItemsCount > itemsCount { + items.insert(.separator, at: itemsCount) + } } else if let channel = peer as? TelegramChannel { if let cachedData = strongSelf.data?.cachedData as? CachedChannelData, cachedData.flags.contains(.canViewStats) { items.append(.action(ContextMenuActionItem(text: presentationData.strings.ChannelInfo_Stats, icon: { theme in @@ -4958,7 +4976,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if case let .user(peer) = peer, let _ = peer.botInfo { strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start()) if !block { - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() if let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id))) } @@ -5372,7 +5390,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate case .help: text = "/help" } - let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)]).start() if let navigationController = strongSelf.controller?.navigationController as? NavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId))) @@ -5493,7 +5511,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }, openPeer: { _ in }, showAll: false) - let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: []) + let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:]) let controller = LocationViewController(context: context, updatedPresentationData: self.controller?.updatedPresentationData, subject: message, params: controllerParams) self.controller?.push(controller) @@ -6056,10 +6074,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate let paintStickersContext = LegacyPaintStickersContext(context: strongSelf.context) paintStickersContext.presentStickersController = { completion in - let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, node, rect in + let controller = DrawingStickersScreen(context: strongSelf.context, selectSticker: { fileReference, view, rect in let coder = PostboxEncoder() coder.encodeRootObject(fileReference.media) - completion?(coder.makeData(), fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, node.view, rect) + completion?(coder.makeData(), fileReference.media.isAnimatedSticker || fileReference.media.isVideoSticker, view, rect) return true }) strongSelf.controller?.present(controller, in: .window(.root)) @@ -6413,7 +6431,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } })) } - + fileprivate func switchToAccount(id: AccountRecordId) { self.accountsAndPeers.set(.never()) self.context.sharedContext.switchToAccount(id: id, fromSettingsController: nil, withChatListController: nil) @@ -6576,7 +6594,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate if !entities.isEmpty { attributes.append(TextEntitiesMessageAttribute(entities: entities)) } - result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) + result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } } } @@ -8527,7 +8545,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { let rect = sourceRect.isEmpty ? sourceNode.bounds : sourceRect - return (sourceNode, rect) + return (sourceNode.view, rect) } else { return nil } diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index cb19f498c2..798e6d568a 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -252,7 +252,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in @@ -329,6 +329,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, schedule: { [weak textInputPanelNode] in textInputPanelNode?.sendMessage(.schedule) }) + controller.emojiViewProvider = textInputPanelNode.emojiViewProvider strongSelf.presentInGlobalOverlay(controller, nil) }, openScheduledMessages: { }, openPeersNearby: { @@ -349,6 +350,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) @@ -383,12 +386,14 @@ final class PeerSelectionControllerNode: ASDisplayNode { func beginSelection() { if let _ = self.textInputPanelNode { } else { - let forwardAccessoryPanelNode = ForwardAccessoryPanelNode(context: self.context, messageIds: self.forwardedMessageIds, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize, nameDisplayOrder: self.presentationData.nameDisplayOrder, forwardOptionsState: self.presentationInterfaceState.interfaceState.forwardOptionsState) + let forwardAccessoryPanelNode = ForwardAccessoryPanelNode(context: self.context, messageIds: self.forwardedMessageIds, theme: self.presentationData.theme, strings: self.presentationData.strings, fontSize: self.presentationData.chatFontSize, nameDisplayOrder: self.presentationData.nameDisplayOrder, forwardOptionsState: self.presentationInterfaceState.interfaceState.forwardOptionsState, animationCache: nil, animationRenderer: nil) forwardAccessoryPanelNode.interfaceInteraction = self.interfaceInteraction self.addSubnode(forwardAccessoryPanelNode) self.forwardAccessoryPanelNode = forwardAccessoryPanelNode - let textInputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) }) + let textInputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) }, makeEntityInputView: { + return nil + }) textInputPanelNode.interfaceInteraction = self.interfaceInteraction textInputPanelNode.sendMessage = { [weak self] mode in guard let strongSelf = self else { @@ -489,7 +494,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { if textInputPanelNode.frame.width.isZero { panelTransition = .immediate } - var panelHeight = textInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height / 2.0, isSecondary: false, transition: panelTransition, interfaceState: self.presentationInterfaceState, metrics: layout.metrics) + var panelHeight = textInputPanelNode.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: layout.size.height / 2.0, isSecondary: false, transition: panelTransition, interfaceState: self.presentationInterfaceState, metrics: layout.metrics, isMediaInputExpanded: false) if self.searchDisplayController == nil { panelHeight += insets.bottom } else { diff --git a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index b1fc27e49a..4469e3bf1a 100644 --- a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift @@ -14,6 +14,9 @@ import TelegramStringFormatting import InvisibleInkDustNode import TextFormat import ChatPresentationInterfaceState +import TextNodeWithEntities +import AnimationCache +import MultiAnimationRenderer final class ReplyAccessoryPanelNode: AccessoryPanelNode { private let messageDisposable = MetaDisposable() @@ -25,7 +28,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { let lineNode: ASImageNode let iconNode: ASImageNode let titleNode: ImmediateTextNode - let textNode: ImmediateTextNode + let textNode: ImmediateTextNodeWithEntities var dustNode: InvisibleInkDustNode? let imageNode: TransformImageNode @@ -36,7 +39,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)? - init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat) { + init(context: AccountContext, messageId: MessageId, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) { self.messageId = messageId self.theme = theme @@ -63,10 +66,21 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { self.titleNode.displaysAsynchronously = false self.titleNode.insets = UIEdgeInsets(top: 3.0, left: 0.0, bottom: 3.0, right: 0.0) - self.textNode = ImmediateTextNode() + self.textNode = ImmediateTextNodeWithEntities() self.textNode.maximumNumberOfLines = 1 self.textNode.displaysAsynchronously = false self.textNode.insets = UIEdgeInsets(top: 3.0, left: 0.0, bottom: 3.0, right: 0.0) + self.textNode.visibility = true + + if let animationCache = animationCache, let animationRenderer = animationRenderer { + self.textNode.arguments = TextNodeWithEntities.Arguments( + context: context, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false + ) + } self.imageNode = TransformImageNode() self.imageNode.contentAnimations = [.subsequentUpdates] @@ -119,7 +133,9 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { default: isMedia = true } - (text, _, isText) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) + let (attributedText, _, isTextValue) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) + text = attributedText.string + isText = isTextValue } else { isMedia = false } @@ -128,15 +144,16 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { let messageText: NSAttributedString if isText, let message = message { let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in - if case .Spoiler = entity.type { + switch entity.type { + case .Spoiler, .CustomEmoji: return true - } else { + default: return false } } let textColor = strongSelf.theme.chat.inputPanel.primaryTextColor if entities.count > 0 { - messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) + messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message) } else { messageText = NSAttributedString(string: text, font: textFont, textColor: isMedia ? strongSelf.theme.chat.inputPanel.secondaryTextColor : strongSelf.theme.chat.inputPanel.primaryTextColor) } diff --git a/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift b/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift index 67053612a4..0dcdecc376 100644 --- a/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/SecretChatHandshakeStatusInputPanelNode.swift @@ -44,7 +44,7 @@ final class SecretChatHandshakeStatusInputPanelNode: ChatInputPanelNode { self.interfaceInteraction?.unblockPeer() } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { if self.presentationInterfaceState != interfaceState { self.presentationInterfaceState = interfaceState diff --git a/submodules/TelegramUI/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Sources/ShareExtensionContext.swift index bd586a1c7f..308fc0332b 100644 --- a/submodules/TelegramUI/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Sources/ShareExtensionContext.swift @@ -237,7 +237,7 @@ public class ShareRootControllerImpl { return nil }) - let sharedContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), resolvedDeviceName: nil), premiumProductId: nil, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) + let sharedContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), resolvedDeviceName: nil), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }) presentationDataPromise.set(sharedContext.presentationData) internalContext = InternalContext(sharedContext: sharedContext) globalInternalContext = internalContext diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index ec89f0bb4b..00ae018e33 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -26,6 +26,7 @@ import AppLock import WallpaperBackgroundNode import InAppPurchaseManager import PremiumUI +import StickerPackPreviewUI private final class AccountUserInterfaceInUseContext { let subscribers = Bag<(Bool) -> Void>() @@ -90,7 +91,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { public let contactDataManager: DeviceContactDataManager? public let locationManager: DeviceLocationManager? public var callManager: PresentationCallManager? - let premiumProductId: String? + let hasInAppPurchases: Bool private var callDisposable: Disposable? private var callStateDisposable: Disposable? @@ -164,7 +165,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { private var spotlightDataContext: SpotlightDataContext? private var widgetDataContext: WidgetDataContext? - public init(mainWindow: Window1?, sharedContainerPath: String, basePath: String, encryptionParameters: ValueBoxEncryptionParameters, accountManager: AccountManager, appLockContext: AppLockContext, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, premiumProductId: String?, rootPath: String, legacyBasePath: String?, apsNotificationToken: Signal, voipNotificationToken: Signal, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) { + public init(mainWindow: Window1?, sharedContainerPath: String, basePath: String, encryptionParameters: ValueBoxEncryptionParameters, accountManager: AccountManager, appLockContext: AppLockContext, applicationBindings: TelegramApplicationBindings, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, networkArguments: NetworkInitializationArguments, hasInAppPurchases: Bool, rootPath: String, legacyBasePath: String?, apsNotificationToken: Signal, voipNotificationToken: Signal, setNotificationCall: @escaping (PresentationCall?) -> Void, navigateToChat: @escaping (AccountRecordId, PeerId, MessageId?) -> Void, displayUpgradeProgress: @escaping (Float?) -> Void = { _ in }) { assert(Queue.mainQueue().isCurrent()) precondition(!testHasInstance) @@ -178,7 +179,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { self.navigateToChatImpl = navigateToChat self.displayUpgradeProgress = displayUpgradeProgress self.appLockContext = appLockContext - self.premiumProductId = premiumProductId + self.hasInAppPurchases = hasInAppPurchases self.accountManager.mediaBox.fetchCachedResourceRepresentation = { (resource, representation) -> Signal in return fetchCachedSharedResourceRepresentation(accountManager: accountManager, resource: resource, representation: representation) @@ -1201,7 +1202,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { return resolveUrlImpl(context: context, peerId: peerId, url: url, skipUrlAuth: skipUrlAuth) } - public func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) { + public func openResolvedUrl(_ resolvedUrl: ResolvedUrl, context: AccountContext, urlContext: OpenURLContext, navigationController: NavigationController?, forceExternal: Bool, openPeer: @escaping (PeerId, ChatControllerInteractionNavigateToPeer) -> Void, sendFile: ((FileMediaReference) -> Void)?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, requestMessageActionUrlAuth: ((MessageActionUrlSubject) -> Void)?, joinVoiceChat: ((PeerId, String?, CachedChannelData.ActiveCall) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, contentContext: Any?) { openResolvedUrlImpl(resolvedUrl, context: context, urlContext: urlContext, navigationController: navigationController, forceExternal: forceExternal, openPeer: openPeer, sendFile: sendFile, sendSticker: sendSticker, requestMessageActionUrlAuth: requestMessageActionUrlAuth, joinVoiceChat: joinVoiceChat, present: present, dismissInput: dismissInput, contentContext: contentContext) } @@ -1280,7 +1281,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { tapMessage?(message) }, clickThroughMessage: { clickThroughMessage?() - }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in + }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _, _, _, _, _ in return false }, sendGif: { _, _, _, _, _ in return false }, sendBotContextResultAsGif: { _, _, _, _, _ in return false }, requestMessageActionCallback: { _, _, _, _ in }, requestMessageActionUrlAuth: { _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openTheme: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in }, presentController: { _, _ in @@ -1313,7 +1314,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in @@ -1333,6 +1334,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, openWebView: { _, _, _, _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { + }, dismissTextInput: { }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false), presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode as? WallpaperBackgroundNode)) @@ -1502,6 +1504,10 @@ public final class SharedAccountContextImpl: SharedAccountContext { } return PremiumIntroScreen(context: context, source: mappedSource) } + + public func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController { + return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, parentNavigationController: parentNavigationController, sendSticker: sendSticker) + } } private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? { diff --git a/submodules/TelegramUI/Sources/StickerPanePeerSpecificSetupGridItem.swift b/submodules/TelegramUI/Sources/StickerPanePeerSpecificSetupGridItem.swift index cdd8f1b469..5f6f4cc4b4 100644 --- a/submodules/TelegramUI/Sources/StickerPanePeerSpecificSetupGridItem.swift +++ b/submodules/TelegramUI/Sources/StickerPanePeerSpecificSetupGridItem.swift @@ -138,7 +138,7 @@ class StickerPanePeerSpecificSetupGridItemNode: GridItemNode { var updateButtonBackgroundImage: UIImage? if currentItem?.theme !== item.theme { updateButtonBackgroundImage = PresentationResourcesChat.chatInputMediaPanelAddPackButtonImage(item.theme) - self.dismissButtonNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(item.theme), for: []) + self.dismissButtonNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(item.theme, color: item.theme.chat.inputMediaPanel.stickersSectionTextColor), for: []) } let leftInset: CGFloat = 12.0 diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift index 3f735b3a4c..4de60fb20e 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift @@ -11,6 +11,7 @@ import LegacyComponents import MergeLists import AccountContext import StickerPackPreviewUI +import StickerPeekUI import Emoji import AppBundle import OverlayStatusController @@ -19,10 +20,10 @@ import UndoUI final class StickerPaneSearchInteraction { let open: (StickerPackCollectionInfo) -> Void let install: (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void - let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Void + let sendSticker: (FileMediaReference, UIView, CGRect) -> Void let getItemIsPreviewed: (StickerPackItem) -> Bool - init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) { + init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void, sendSticker: @escaping (FileMediaReference, UIView, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) { self.open = open self.install = install self.sendSticker = sendSticker @@ -100,7 +101,7 @@ private enum StickerSearchEntry: Identifiable, Comparable { switch self { case let .sticker(_, code, stickerItem, theme): return StickerPaneSearchStickerItem(account: account, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in - interaction.sendSticker(.standalone(media: stickerItem.file), node, rect) + interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect) }) case let .global(_, info, topItems, installed, topSeparator): let itemContext = StickerPaneSearchGlobalItemContext() @@ -186,7 +187,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { self.strings = strings self.trendingPane = ChatMediaInputTrendingPane(context: context, controllerInteraction: controllerInteraction, getItemIsPreviewed: { [weak inputNodeInteraction] item in - return inputNodeInteraction?.previewedStickerPackItem == .pack(item) + return inputNodeInteraction?.previewedStickerPackItem == .pack(item.file) }, isPane: false) self.gridNode = GridNode() @@ -226,7 +227,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { let packReference: StickerPackReference = .id(id: info.id.id, accessHash: info.accessHash) let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: strongSelf.controllerInteraction.navigationController(), sendSticker: { [weak self] fileReference, sourceNode, sourceRect in if let strongSelf = self { - return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect) + return strongSelf.controllerInteraction.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil) } else { return false } @@ -319,12 +320,12 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { |> deliverOnMainQueue).start(next: { _ in }) } - }, sendSticker: { [weak self] file, sourceNode, sourceRect in + }, sendSticker: { [weak self] file, sourceView, sourceRect in if let strongSelf = self { - let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect) + let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil) } }, getItemIsPreviewed: { item in - return inputNodeInteraction.previewedStickerPackItem == .pack(item) + return inputNodeInteraction.previewedStickerPackItem == .pack(item.file) }) self._ready.set(self.trendingPane.ready) @@ -561,7 +562,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { func itemAt(point: CGPoint) -> (ASDisplayNode, Any)? { if !self.trendingPane.isHidden { if let (itemNode, item) = self.trendingPane.itemAt(point: self.view.convert(point, to: self.trendingPane.view)) { - return (itemNode, StickerPreviewPeekItem.pack(item)) + return (itemNode, StickerPreviewPeekItem.pack(item.file)) } } else { if let itemNode = self.gridNode.itemNodeAtPoint(self.view.convert(point, to: self.gridNode.view)) { @@ -569,7 +570,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { return (itemNode, StickerPreviewPeekItem.found(stickerItem)) } else if let itemNode = itemNode as? StickerPaneSearchGlobalItemNode { if let (node, item) = itemNode.itemAt(point: self.view.convert(point, to: itemNode.view)) { - return (node, StickerPreviewPeekItem.pack(item)) + return (node, StickerPreviewPeekItem.pack(item.file)) } } } diff --git a/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift b/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift index 66eb834827..19dd723f22 100644 --- a/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift +++ b/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift @@ -525,7 +525,7 @@ class StickerPaneTrendingListGridItemNode: GridItemNode { self.listView.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) if currentItem?.theme !== item.theme { - self.dismissButtonNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(item.theme), for: []) + self.dismissButtonNode.setImage(PresentationResourcesChat.chatInputMediaPanelGridDismissImage(item.theme, color: item.theme.chat.inputMediaPanel.stickersSectionTextColor), for: []) } let leftInset: CGFloat = 9.0 diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift index a0055a4545..ea088a38f6 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift @@ -126,7 +126,7 @@ final class StickersChatInputContextPanelItemNode: ListViewItemNode { for i in 0 ..< self.nodes.count { if self.nodes[i].frame.contains(location) { let file = item.files[i] - let _ = item.interfaceInteraction.sendSticker(.standalone(media: file), true, self.nodes[i], self.nodes[i].bounds) + let _ = item.interfaceInteraction.sendSticker(.standalone(media: file), true, self.nodes[i].view, self.nodes[i].bounds, nil) break } } @@ -162,7 +162,7 @@ final class StickersChatInputContextPanelItemNode: ListViewItemNode { var previewingIndex: Int? = nil for i in 0 ..< item.files.count { - if item.stickersInteraction.previewedStickerItem == self.stickerItem(at: i) { + if item.stickersInteraction.previewedStickerItem?.fileId == self.stickerItem(at: i)?.file.fileId { previewingIndex = i break } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index b31262461c..76c41904a1 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -10,6 +10,7 @@ import TelegramUIPreferences import MergeLists import AccountContext import StickerPackPreviewUI +import StickerPeekUI import ContextUI import ChatPresentationInterfaceState import PremiumUI @@ -20,7 +21,7 @@ private struct StickersChatInputContextPanelEntryStableId: Hashable { } final class StickersChatInputContextPanelInteraction { - var previewedStickerItem: StickerPackItem? + var previewedStickerItem: TelegramMediaFile? } private struct StickersChatInputContextPanelEntry: Identifiable, Comparable { @@ -84,7 +85,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { private var stickerPreviewController: StickerPreviewController? - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.strings = strings self.listView = ListView() @@ -99,7 +100,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { self.stickersInteraction = StickersChatInputContextPanelInteraction() - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true @@ -129,14 +130,14 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { if let (item, itemNode) = stickersNode.stickerItem(at: point) { return strongSelf.context.engine.stickers.isStickerSaved(id: item.file.fileId) |> deliverOnMainQueue - |> map { isStarred -> (ASDisplayNode, PeekControllerContent)? in + |> map { isStarred -> (UIView, CGRect, PeekControllerContent)? in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { var menuItems: [ContextMenuItem] = [] menuItems = [ .action(ContextMenuActionItem(text: strongSelf.strings.StickerPack_Send, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { _, f in f(.default) - let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode, itemNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, false, nil, true, itemNode.view, itemNode.bounds, nil) })), .action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.default) @@ -147,7 +148,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil) + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil, customAction: nil), elevatedLayout: false, action: { _ in return false }), nil) case let .limitExceeded(limit, premiumLimit): let premiumConfiguration = PremiumConfiguration.with(appConfiguration: strongSelf.context.currentAppConfiguration.with { $0 }) let text: String @@ -156,7 +157,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { } else { text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in + strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil, customAction: nil), elevatedLayout: false, action: { [weak self] action in if let strongSelf = self { if case .info = action { let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers) @@ -180,7 +181,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { if let packReference = packReference { let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controllerInteraction.navigationController(), sendSticker: { file, sourceNode, sourceRect in if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction { - return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect) + return controllerInteraction.sendSticker(file, false, false, nil, true, sourceNode, sourceRect, nil) } else { return false } @@ -197,7 +198,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { [weak self] in + return (itemNode.view, itemNode.bounds, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item.file), menu: menuItems, openPremiumIntro: { [weak self] in guard let strongSelf = self else { return } @@ -212,11 +213,11 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { } } return nil - }, present: { [weak self] content, sourceNode in + }, present: { [weak self] content, sourceView, sourceRect in if let strongSelf = self { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = PeekController(presentationData: presentationData, content: content, sourceNode: { - return sourceNode + let controller = PeekController(presentationData: presentationData, content: content, sourceView: { + return (sourceView, sourceRect) }) strongSelf.interfaceInteraction?.presentGlobalOverlayController(controller, nil) return controller @@ -224,18 +225,18 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { return nil }, updateContent: { [weak self] content in if let strongSelf = self { - var item: StickerPackItem? + var item: TelegramMediaFile? if let content = content as? StickerPreviewPeekContent, case let .pack(contentItem) = content.item { item = contentItem } - strongSelf.updatePreviewingItem(item: item, animated: true) + strongSelf.updatePreviewingItem(file: item, animated: true) } })) } - private func updatePreviewingItem(item: StickerPackItem?, animated: Bool) { - if self.stickersInteraction.previewedStickerItem != item { - self.stickersInteraction.previewedStickerItem = item + private func updatePreviewingItem(file: TelegramMediaFile?, animated: Bool) { + if self.stickersInteraction.previewedStickerItem?.fileId != file?.fileId { + self.stickersInteraction.previewedStickerItem = file self.listView.forEachItemNode { itemNode in if let itemNode = itemNode as? StickersChatInputContextPanelItemNode { diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 57ddcbac1b..ab664bfbc6 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -74,14 +74,13 @@ public final class TelegramRootController: NavigationController { } }) - self.applicationInFocusDisposable = (context.sharedContext.applicationBindings.applicationIsActive - |> distinctUntilChanged - |> deliverOn(Queue.mainQueue())).start(next: { [weak self] value in - guard let strongSelf = self else { - return - } - strongSelf.setForceBadgeHidden(!value) - }) + if context.sharedContext.applicationBindings.isMainApp { + self.applicationInFocusDisposable = (context.sharedContext.applicationBindings.applicationIsActive + |> distinctUntilChanged + |> deliverOn(Queue.mainQueue())).start(next: { value in + context.sharedContext.mainWindow?.setForceBadgeHidden(!value) + }) + } } required public init(coder aDecoder: NSCoder) { @@ -126,11 +125,11 @@ public final class TelegramRootController: NavigationController { } let accountSettingsController = PeerInfoScreenImpl(context: self.context, updatedPresentationData: nil, peerId: self.context.account.peerId, avatarInitiallyExpanded: false, isOpenedFromChat: false, nearbyPeerDistance: nil, callMessages: [], isSettings: true) - accountSettingsController.tabBarItemDebugTapAction = { [weak self, weak accountSettingsController] in - guard let strongSelf = self, let accountSettingsController = accountSettingsController else { + accountSettingsController.tabBarItemDebugTapAction = { [weak self] in + guard let strongSelf = self else { return } - accountSettingsController.push(debugController(sharedContext: strongSelf.context.sharedContext, context: strongSelf.context)) + strongSelf.pushViewController(debugController(sharedContext: strongSelf.context.sharedContext, context: strongSelf.context)) } controllers.append(accountSettingsController) diff --git a/submodules/TelegramUI/Sources/TextLinkHandling.swift b/submodules/TelegramUI/Sources/TextLinkHandling.swift index 7c5934906d..d1098bf776 100644 --- a/submodules/TelegramUI/Sources/TextLinkHandling.swift +++ b/submodules/TelegramUI/Sources/TextLinkHandling.swift @@ -67,7 +67,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate controller?.present(c, in: .window(.root), with: a) }, messageId: replyThreadMessage.messageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).start() } - case let .stickerPack(name): + case let .stickerPack(name, _): let packReference: StickerPackReference = .name(name) controller.present(StickerPackScreen(context: context, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root)) case let .instantView(webpage, anchor): @@ -76,12 +76,6 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId, peekData in openResolvedPeerImpl(peerId, .chat(textInputState: nil, subject: nil, peekData: peekData)) }, parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root)) - #if ENABLE_WALLET - case let .wallet(address, amount, comment): - context.sharedContext.openWallet(context: context, walletContext: .send(address: address, amount: amount, comment: comment)) { c in - (controller.navigationController as? NavigationController)?.pushViewController(c) - } - #endif default: break } diff --git a/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift index 4909d96e51..4574657846 100644 --- a/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/VerticalListContextResultsChatInputContextPanelNode.swift @@ -133,7 +133,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex private let loadMoreDisposable = MetaDisposable() private var isLoadingMore: Bool = false - override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize) { + override init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, fontSize: PresentationFontSize, chatPresentationContext: ChatPresentationContext) { self.listView = ListView() self.listView.isOpaque = false self.listView.stackFromBottom = true @@ -145,7 +145,7 @@ final class VerticalListContextResultsChatInputContextPanelNode: ChatInputContex return strings.VoiceOver_ScrollStatus(row, count).string } - super.init(context: context, theme: theme, strings: strings, fontSize: fontSize) + super.init(context: context, theme: theme, strings: strings, fontSize: fontSize, chatPresentationContext: chatPresentationContext) self.isOpaque = false self.clipsToBounds = true diff --git a/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift index c4a682e23d..f588bb8561 100644 --- a/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift @@ -135,14 +135,14 @@ final class WebpagePreviewAccessoryPanelNode: AccessoryPanelNode { } else if content.type == "telegram_theme" { text = strings.Message_Theme } else { - text = stringForMediaKind(mediaKind, strings: self.strings).0 + text = stringForMediaKind(mediaKind, strings: self.strings).0.string } } else if content.type == "telegram_theme" { text = strings.Message_Theme } else if content.type == "video" { - text = stringForMediaKind(.video, strings: self.strings).0 + text = stringForMediaKind(.video, strings: self.strings).0.string } else if let _ = content.image { - text = stringForMediaKind(.image, strings: self.strings).0 + text = stringForMediaKind(.image, strings: self.strings).0.string } } diff --git a/submodules/TelegramUniversalVideoContent/Sources/ExternalVideoPlayer.swift b/submodules/TelegramUniversalVideoContent/Sources/ExternalVideoPlayer.swift new file mode 100644 index 0000000000..eceba5b1dd --- /dev/null +++ b/submodules/TelegramUniversalVideoContent/Sources/ExternalVideoPlayer.swift @@ -0,0 +1,121 @@ +import Foundation +import AVFoundation +import SwiftSignalKit +import UniversalMediaPlayer +import AccountContext +import AVKit + +public class ExternalVideoPlayer: NSObject, AVRoutePickerViewDelegate { + private let context: AccountContext + let content: NativeVideoContent + + let player: AVPlayer? + private var didPlayToEndTimeObserver: NSObjectProtocol? + private var timeObserver: Any? + + private var statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: false, progress: 0.0, display: true), soundEnabled: true) + private let _status = ValuePromise() + var status: Signal { + return self._status.get() + } + private var seekId: Int = 0 + + private weak var routePickerView: UIView? + + public var isActiveUpdated: (Bool) -> Void = { _ in } + + public init(context: AccountContext, content: NativeVideoContent) { + self.context = context + self.content = content + + if let path = context.account.postbox.mediaBox.completedResourcePath(content.fileReference.media.resource, pathExtension: "mp4") { + let player = AVPlayer(url: URL(fileURLWithPath: path)) + self.player = player + } else { + self.player = nil + } + + super.init() + + self.startObservingForAirPlayStatusChanges() + self.isActiveUpdated(self.player?.isExternalPlaybackActive ?? false) + + if let player = self.player { + self.didPlayToEndTimeObserver = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player.currentItem, queue: nil, using: { [weak self] notification in + if let strongSelf = self { + strongSelf.player?.seek(to: CMTime(seconds: 0.0, preferredTimescale: 30)) + strongSelf.play() + } + }) + + self.timeObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 10), queue: DispatchQueue.main) { [weak self] time in + guard let strongSelf = self else { + return + } + strongSelf.statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: strongSelf.statusValue.duration, dimensions: CGSize(), timestamp: CMTimeGetSeconds(time), baseRate: 1.0, seekId: strongSelf.seekId, status: strongSelf.statusValue.status, soundEnabled: true) + strongSelf._status.set(strongSelf.statusValue) + } + } + + self._status.set(self.statusValue) + } + + deinit { + if let timeObserver = self.timeObserver { + self.player?.removeTimeObserver(timeObserver) + } + + if let didPlayToEndTimeObserver = self.didPlayToEndTimeObserver { + NotificationCenter.default.removeObserver(didPlayToEndTimeObserver) + } + + self.stopObservingForAirPlayStatusChanges() + } + + public func play() { + self.player?.play() + } + + public func openRouteSelection() { + if #available(iOS 11.0, *) { + let routePickerView = AVRoutePickerView() + routePickerView.delegate = self + if #available(iOS 13.0, *) { + routePickerView.prioritizesVideoDevices = true + } + self.context.sharedContext.mainWindow?.viewController?.view.addSubview(routePickerView) + + if let routePickerButton = routePickerView.subviews.first(where: { $0 is UIButton }) as? UIButton { + routePickerButton.sendActions(for: .touchUpInside) + } + } + } + + @available(iOS 11.0, *) + public func routePickerViewDidEndPresentingRoutes(_ routePickerView: AVRoutePickerView) { + routePickerView.removeFromSuperview() + + self.play() + } + + private var observerContextAirplay = 1 + + func startObservingForAirPlayStatusChanges() + { + self.player?.addObserver(self, forKeyPath: #keyPath(AVPlayer.isExternalPlaybackActive), options: .new, context: &observerContextAirplay) + } + + func stopObservingForAirPlayStatusChanges() + { + self.player?.removeObserver(self, forKeyPath: #keyPath(AVPlayer.isExternalPlaybackActive)) + } + + public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + if context == &observerContextAirplay { + self.isActiveUpdated(self.player?.isExternalPlaybackActive ?? false) + } + else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + } +} diff --git a/submodules/TelegramUpdateUI/Sources/UpdateInfoItem.swift b/submodules/TelegramUpdateUI/Sources/UpdateInfoItem.swift index e67a9f4807..02f9e76230 100644 --- a/submodules/TelegramUpdateUI/Sources/UpdateInfoItem.swift +++ b/submodules/TelegramUpdateUI/Sources/UpdateInfoItem.swift @@ -212,7 +212,7 @@ class UpdateInfoItemNode: ListViewItemNode { let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: textColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 88.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let string = stringWithAppliedEntities(item.text, entities: item.entities, baseColor: textColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont) + let string = stringWithAppliedEntities(item.text, entities: item.entities, baseColor: textColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont, message: nil) let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 28.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let contentSize: CGSize diff --git a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift index f9dbd1d6e7..172113d076 100644 --- a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift +++ b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift @@ -3,6 +3,7 @@ import UIKit import Display import AsyncDisplayKit import Postbox +import TelegramCore import TelegramPresentationData import Emoji @@ -17,10 +18,13 @@ public struct ChatTextInputAttributes { public static let textMention = NSAttributedString.Key(rawValue: "Attribute__TextMention") public static let textUrl = NSAttributedString.Key(rawValue: "Attribute__TextUrl") public static let spoiler = NSAttributedString.Key(rawValue: "Attribute__Spoiler") + public static let customEmoji = NSAttributedString.Key(rawValue: "Attribute__CustomEmoji") - public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler] + public static let allAttributes = [ChatTextInputAttributes.bold, ChatTextInputAttributes.italic, ChatTextInputAttributes.monospace, ChatTextInputAttributes.strikethrough, ChatTextInputAttributes.underline, ChatTextInputAttributes.textMention, ChatTextInputAttributes.textUrl, ChatTextInputAttributes.spoiler, ChatTextInputAttributes.customEmoji] } +public let originalTextAttributeKey = NSAttributedString.Key(rawValue: "Attribute__OriginalText") + public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttributedString { let sourceString = NSMutableAttributedString(attributedString: text) while true { @@ -28,7 +32,7 @@ public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttrib let fullRange = NSRange(sourceString.string.startIndex ..< sourceString.string.endIndex, in: sourceString.string) sourceString.enumerateAttribute(NSAttributedString.Key.attachment, in: fullRange, options: [.longestEffectiveRangeNotRequired], using: { value, range, stop in if let value = value as? EmojiTextAttachment { - sourceString.replaceCharacters(in: range, with: NSAttributedString(string: value.emoji)) + sourceString.replaceCharacters(in: range, with: NSAttributedString(string: value.text, attributes: [ChatTextInputAttributes.customEmoji: value.emoji])) stop.pointee = true found = true } @@ -64,7 +68,7 @@ public struct ChatTextFontAttributes: OptionSet { public static let blockQuote = ChatTextFontAttributes(rawValue: 1 << 3) } -public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set, emojiViewProvider: ((String) -> UIView)?) -> NSAttributedString { +public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) -> NSAttributedString { let result = NSMutableAttributedString(string: stateText.string) let fullRange = NSRange(location: 0, length: result.length) @@ -108,6 +112,8 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo } else { result.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range) } + } else if key == ChatTextInputAttributes.customEmoji { + result.addAttribute(key, value: value, range: range) } } @@ -135,35 +141,6 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo } }) - /*if #available(iOS 15, *), let emojiViewProvider = emojiViewProvider { - let _ = CustomTextAttachmentViewProvider.ensureRegistered - - var nextIndex: [String: Int] = [:] - - result.string.enumerateSubstrings(in: result.string.startIndex ..< result.string.endIndex, options: [.byComposedCharacterSequences]) { substring, substringRange, _, stop in - if let substring = substring { - let emoji = substring.basicEmoji.0 - - if !emoji.isEmpty && emoji.isSingleEmoji && availableEmojis.contains(emoji) { - let index: Int - if let value = nextIndex[emoji] { - index = value - } else { - index = 0 - } - nextIndex[emoji] = index + 1 - - let attachment = EmojiTextAttachment(index: index, emoji: emoji, viewProvider: emojiViewProvider) - attachment.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 26.0, height: 16.0)) - - result.replaceCharacters(in: NSRange(substringRange, in: result.string), with: NSAttributedString(attachment: attachment)) - - stop = true - } - } - } - }*/ - return result } @@ -215,6 +192,29 @@ public final class ChatTextInputTextUrlAttribute: NSObject { } } +public final class ChatTextInputTextCustomEmojiAttribute: NSObject { + public let stickerPack: StickerPackReference? + public let fileId: Int64 + public let file: TelegramMediaFile? + + public init(stickerPack: StickerPackReference?, fileId: Int64, file: TelegramMediaFile?) { + self.stickerPack = stickerPack + self.fileId = fileId + self.file = file + + super.init() + } + + override public func isEqual(_ object: Any?) -> Bool { + if let other = object as? ChatTextInputTextCustomEmojiAttribute { + return self === other + //return self.stickerPack == other.stickerPack && self.fileId == other.fileId && self.file?.fileId == other.file?.fileId + } else { + return false + } + } +} + private func textUrlRangesEqual(_ lhs: [(NSRange, ChatTextInputTextUrlAttribute)], _ rhs: [(NSRange, ChatTextInputTextUrlAttribute)]) -> Bool { if lhs.count != rhs.count { return false @@ -459,7 +459,7 @@ private func refreshTextUrls(text: NSString, initialAttributedText: NSAttributed } } -public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set, emojiViewProvider: ((String) -> UIView)?) { +public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, spoilersRevealed: Bool, availableEmojis: Set, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) { guard let initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else { return } @@ -493,10 +493,14 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.textMention, range: fullRange) textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.textUrl, range: fullRange) textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.spoiler, range: fullRange) + textNode.textView.textStorage.removeAttribute(ChatTextInputAttributes.customEmoji, range: fullRange) textNode.textView.textStorage.addAttribute(NSAttributedString.Key.font, value: Font.regular(baseFontSize), range: fullRange) textNode.textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: theme.chat.inputPanel.primaryTextColor, range: fullRange) + let replaceRanges: [(NSRange, EmojiTextAttachment)] = [] + + //var emojiIndex = 0 attributedText.enumerateAttributes(in: fullRange, options: [], using: { attributes, range, _ in var fontAttributes: ChatTextFontAttributes = [] @@ -530,6 +534,8 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme } else { textNode.textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range) } + } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { + textNode.textView.textStorage.addAttribute(key, value: value, range: range) } } @@ -556,56 +562,14 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme } } }) - } - - if #available(iOS 15, *), let emojiViewProvider = emojiViewProvider { - let _ = CustomTextAttachmentViewProvider.ensureRegistered - var nextIndex: [String: Int] = [:] - - var count = 0 - - let fullRange = NSRange(textNode.textView.textStorage.string.startIndex ..< textNode.textView.textStorage.string.endIndex, in: textNode.textView.textStorage.string) - textNode.textView.textStorage.enumerateAttribute(NSAttributedString.Key.attachment, in: fullRange, options: [], using: { value, _, _ in - if let _ = value as? EmojiTextAttachment { - count += 1 - } - }) - - while count < 10 { - var found = false - textNode.textView.textStorage.string.enumerateSubstrings(in: textNode.textView.textStorage.string.startIndex ..< textNode.textView.textStorage.string.endIndex, options: [.byComposedCharacterSequences]) { substring, substringRange, _, stop in - if let substring = substring { - let emoji = substring.basicEmoji.0 - - if !emoji.isEmpty && emoji.isSingleEmoji && availableEmojis.contains(emoji) { - let index: Int - if let value = nextIndex[emoji] { - index = value - } else { - index = 0 - } - nextIndex[emoji] = index + 1 - - let attachment = EmojiTextAttachment(index: index, emoji: emoji, viewProvider: emojiViewProvider) - attachment.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 26.0, height: 16.0)) - - textNode.textView.textStorage.replaceCharacters(in: NSRange(substringRange, in: textNode.textView.textStorage.string), with: NSAttributedString(attachment: attachment)) - - count += 1 - found = true - stop = true - } - } - } - if !found { - break - } + for (range, attachment) in replaceRanges.sorted(by: { $0.0.location > $1.0.location }) { + textNode.textView.textStorage.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment)) } } } -public func refreshGenericTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, availableEmojis: Set, emojiViewProvider: ((String) -> UIView)?, spoilersRevealed: Bool = false) { +public func refreshGenericTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, availableEmojis: Set, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, spoilersRevealed: Bool = false) { guard let initialAttributedText = textNode.attributedText, initialAttributedText.length != 0 else { return } @@ -902,10 +866,12 @@ public func convertMarkdownToAttributes(_ text: NSAttributedString) -> NSAttribu } private final class EmojiTextAttachment: NSTextAttachment { - let emoji: String - let viewProvider: (String) -> UIView + let text: String + let emoji: ChatTextInputTextCustomEmojiAttribute + let viewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView - init(index: Int, emoji: String, viewProvider: @escaping (String) -> UIView) { + init(index: Int, text: String, emoji: ChatTextInputTextCustomEmojiAttribute, viewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView) { + self.text = text self.emoji = emoji self.viewProvider = viewProvider diff --git a/submodules/TextFormat/Sources/GenerateTextEntities.swift b/submodules/TextFormat/Sources/GenerateTextEntities.swift index dbaa90b7a6..35efbe4f81 100644 --- a/submodules/TextFormat/Sources/GenerateTextEntities.swift +++ b/submodules/TextFormat/Sources/GenerateTextEntities.swift @@ -145,26 +145,6 @@ private func commitEntity(_ utf16: String.UTF16View, _ type: CurrentEntityType, public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimatedEmojisInText: Int? = nil) -> [MessageTextEntity] { var entities: [MessageTextEntity] = [] - - if let maxAnimatedEmojisInText = maxAnimatedEmojisInText, maxAnimatedEmojisInText != 0 { - var count = 0 - text.string.enumerateSubstrings(in: text.string.startIndex ..< text.string.endIndex, options: [.byComposedCharacterSequences], { substring, substringRange, _, stop in - if let substring = substring { - let emoji = substring.basicEmoji.0 - - if !emoji.isEmpty && emoji.isSingleEmoji { - let mappedRange = NSRange(substringRange, in: text.string) - - entities.append(MessageTextEntity(range: mappedRange.lowerBound ..< mappedRange.upperBound, type: .AnimatedEmoji(nil))) - - count += 1 - if count >= maxAnimatedEmojisInText { - stop = true - } - } - } - }) - } text.enumerateAttributes(in: NSRange(location: 0, length: text.length), options: [], using: { attributes, range, _ in for (key, value) in attributes { @@ -184,6 +164,8 @@ public func generateChatInputTextEntities(_ text: NSAttributedString, maxAnimate entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .TextUrl(url: value.url))) } else if key == ChatTextInputAttributes.spoiler { entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .Spoiler)) + } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { + entities.append(MessageTextEntity(range: range.lowerBound ..< range.upperBound, type: .CustomEmoji(stickerPack: value.stickerPack, fileId: value.fileId))) } } }) diff --git a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index afde2592a1..d24684327b 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -1,5 +1,6 @@ import Foundation import UIKit +import Postbox import TelegramCore public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [MessageTextEntity]) -> NSAttributedString { @@ -40,6 +41,8 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M string.addAttribute(ChatTextInputAttributes.underline, value: true as NSNumber, range: range) case .Spoiler: string.addAttribute(ChatTextInputAttributes.spoiler, value: true as NSNumber, range: range) + case let .CustomEmoji(stickerPack, fileId): + string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: range) default: break } @@ -47,7 +50,7 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M return string } -public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false) -> NSAttributedString { +public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?) -> NSAttributedString { var nsString: NSString? let string = NSMutableAttributedString(string: text, attributes: [NSAttributedString.Key.font: baseFont, NSAttributedString.Key.foregroundColor: baseColor]) var skipEntity = false @@ -247,6 +250,8 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Timecode), value: TelegramTimecode(time: time, text: text), range: range) } } + case let .CustomEmoji(stickerPack, fileId): + string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: message?.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) default: break } diff --git a/submodules/TextSelectionNode/BUILD b/submodules/TextSelectionNode/BUILD index 05e706d364..2bb977e11c 100644 --- a/submodules/TextSelectionNode/BUILD +++ b/submodules/TextSelectionNode/BUILD @@ -13,6 +13,7 @@ swift_library( "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", "//submodules/TelegramPresentationData:TelegramPresentationData", + "//submodules/TextFormat:TextFormat", ], visibility = [ "//visibility:public", diff --git a/submodules/TextSelectionNode/Sources/TextSelectionNode.swift b/submodules/TextSelectionNode/Sources/TextSelectionNode.swift index 930eaaf914..8b58713f3a 100644 --- a/submodules/TextSelectionNode/Sources/TextSelectionNode.swift +++ b/submodules/TextSelectionNode/Sources/TextSelectionNode.swift @@ -4,6 +4,7 @@ import UIKit.UIGestureRecognizerSubclass import AsyncDisplayKit import Display import TelegramPresentationData +import TextFormat private func findScrollView(view: UIView?) -> UIScrollView? { if let view = view { @@ -494,20 +495,43 @@ public final class TextSelectionNode: ASDisplayNode { } completeRect = completeRect.insetBy(dx: 0.0, dy: -12.0) - let attributedText = attributedString.attributedSubstring(from: range) + let string = NSMutableAttributedString(attributedString: attributedString.attributedSubstring(from: range)) + + var fullRange = NSRange(location: 0, length: string.length) + while true { + var found = false + string.enumerateAttribute(originalTextAttributeKey, in: fullRange, options: [], using: { value, range, stop in + if let value = value as? String { + let updatedSubstring = NSMutableAttributedString(string: value) + + let replacementRange = NSRange(location: 0, length: updatedSubstring.length) + updatedSubstring.addAttributes(string.attributes(at: range.location, effectiveRange: nil), range: replacementRange) + + string.replaceCharacters(in: range, with: updatedSubstring) + let updatedRange = NSRange(location: range.location, length: updatedSubstring.length) + + found = true + stop.pointee = ObjCBool(true) + fullRange = NSRange(location: updatedRange.upperBound, length: fullRange.upperBound - range.upperBound) + } + }) + if !found { + break + } + } var actions: [ContextMenuAction] = [] actions.append(ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuCopy, accessibilityLabel: self.strings.Conversation_ContextMenuCopy), action: { [weak self] in - self?.performAction(attributedText, .copy) + self?.performAction(string, .copy) self?.dismissSelection() })) actions.append(ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuLookUp, accessibilityLabel: self.strings.Conversation_ContextMenuLookUp), action: { [weak self] in - self?.performAction(attributedText, .lookup) + self?.performAction(string, .lookup) self?.dismissSelection() })) if #available(iOS 15.0, *) { actions.append(ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuTranslate, accessibilityLabel: self.strings.Conversation_ContextMenuTranslate), action: { [weak self] in - self?.performAction(attributedText, .translate) + self?.performAction(string, .translate) self?.dismissSelection() })) } @@ -518,7 +542,7 @@ public final class TextSelectionNode: ASDisplayNode { // })) // } actions.append(ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuShare, accessibilityLabel: self.strings.Conversation_ContextMenuShare), action: { [weak self] in - self?.performAction(attributedText, .share) + self?.performAction(string, .share) self?.dismissSelection() })) diff --git a/submodules/TooltipUI/Sources/TooltipScreen.swift b/submodules/TooltipUI/Sources/TooltipScreen.swift index a936170e91..cb87f87530 100644 --- a/submodules/TooltipUI/Sources/TooltipScreen.swift +++ b/submodules/TooltipUI/Sources/TooltipScreen.swift @@ -192,7 +192,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode { self.textNode.displaysAsynchronously = false self.textNode.maximumNumberOfLines = 0 - self.textNode.attributedText = stringWithAppliedEntities(text, entities: textEntities, baseColor: .white, linkColor: .white, baseFont: Font.regular(fontSize), linkFont: Font.regular(fontSize), boldFont: Font.semibold(14.0), italicFont: Font.italic(fontSize), boldItalicFont: Font.semiboldItalic(fontSize), fixedFont: Font.monospace(fontSize), blockQuoteFont: Font.regular(fontSize), underlineLinks: true, external: false) + self.textNode.attributedText = stringWithAppliedEntities(text, entities: textEntities, baseColor: .white, linkColor: .white, baseFont: Font.regular(fontSize), linkFont: Font.regular(fontSize), boldFont: Font.semibold(14.0), italicFont: Font.italic(fontSize), boldItalicFont: Font.semiboldItalic(fontSize), fixedFont: Font.monospace(fontSize), blockQuoteFont: Font.regular(fontSize), underlineLinks: true, external: false, message: nil) self.animatedStickerNode = DefaultAnimatedStickerNodeImpl() switch icon { diff --git a/submodules/TouchDownGesture/Sources/TouchDownGestureRecognizer.swift b/submodules/TouchDownGesture/Sources/TouchDownGestureRecognizer.swift index 2b5a981b6c..22ed7f1421 100644 --- a/submodules/TouchDownGesture/Sources/TouchDownGestureRecognizer.swift +++ b/submodules/TouchDownGesture/Sources/TouchDownGestureRecognizer.swift @@ -6,7 +6,8 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize public var touchDown: (() -> Void)? private var touchLocation: CGPoint? - public var waitForTouchUp = false + public var waitForTouchUp: (() -> Bool)? + private var isWaitingForTouchUp: Bool = false override public init(target: Any?, action: Selector?) { super.init(target: target, action: action) @@ -14,6 +15,13 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize self.delegate = self } + override public func reset() { + self.touchLocation = nil + self.isWaitingForTouchUp = false + + super.reset() + } + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } @@ -21,7 +29,8 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize override public func touchesBegan(_ touches: Set, with event: UIEvent) { super.touchesBegan(touches, with: event) - if self.waitForTouchUp { + if let waitForTouchUp = self.waitForTouchUp, waitForTouchUp() { + self.isWaitingForTouchUp = true if let touch = touches.first { self.touchLocation = touch.location(in: self.view) } @@ -49,14 +58,9 @@ public class TouchDownGestureRecognizer: UIGestureRecognizer, UIGestureRecognize override public func touchesEnded(_ touches: Set, with event: UIEvent) { super.touchesEnded(touches, with: event) - if let touchDown = self.touchDown, self.waitForTouchUp { + if let touchDown = self.touchDown, self.isWaitingForTouchUp { + self.isWaitingForTouchUp = false touchDown() } } - - override public func reset() { - self.touchLocation = nil - - super.reset() - } } diff --git a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIKitUtils.m b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIKitUtils.m index a58c63b7c8..9241d2297b 100644 --- a/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIKitUtils.m +++ b/submodules/UIKitRuntimeUtils/Source/UIKitRuntimeUtils/UIKitUtils.m @@ -169,46 +169,31 @@ void applySmoothRoundedCornersImpl(CALayer * _Nonnull layer) { } } -/*@interface _UIPortalView : UIView - -@property(nonatomic, getter=_isGeometryFrozen, setter=_setGeometryFrozen:) _Bool _geometryFrozen; // @synthesize _geometryFrozen=__geometryFrozen; -@property(nonatomic) _Bool forwardsClientHitTestingToSourceView; // @synthesize forwardsClientHitTestingToSourceView=_forwardsClientHitTestingToSourceView; -@property(copy, nonatomic) NSString * _Nullable name; // @synthesize name=_name; -@property(nonatomic) __weak UIView * _Nullable sourceView; // @synthesize sourceView=_sourceView; -- (void)setCenter:(struct CGPoint)arg1; -- (void)setBounds:(struct CGRect)arg1; -- (void)setFrame:(struct CGRect)arg1; -- (void)setHidden:(_Bool)arg1; -@property(nonatomic) _Bool allowsHitTesting; // @dynamic allowsHitTesting; -@property(nonatomic) _Bool allowsBackdropGroups; // @dynamic allowsBackdropGroups; -@property(nonatomic) _Bool matchesPosition; // @dynamic matchesPosition; -@property(nonatomic) _Bool matchesTransform; // @dynamic matchesTransform; -@property(nonatomic) _Bool matchesAlpha; // @dynamic matchesAlpha; -@property(nonatomic) _Bool hidesSourceView; // @dynamic hidesSourceView; -- (instancetype _Nonnull)initWithFrame:(struct CGRect)arg1; -- (instancetype _Nonnull)initWithSourceView:(UIView * _Nullable)arg1; - -@end*/ - UIView * _Nullable makePortalView() { - static Class portalViewClass = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - portalViewClass = NSClassFromString([@[@"_", @"UI", @"Portal", @"View"] componentsJoinedByString:@""]); - }); - if (!portalViewClass) { + if (@available(iOS 12.0, *)) { + static Class portalViewClass = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + portalViewClass = NSClassFromString([@[@"_", @"UI", @"Portal", @"View"] componentsJoinedByString:@""]); + }); + if (!portalViewClass) { + return nil; + } + UIView *view = [[portalViewClass alloc] init]; + if (!view) { + return nil; + } + + if (@available(iOS 13.0, *)) { + view.forwardsClientHitTestingToSourceView = false; + } + view.matchesPosition = true; + view.matchesTransform = true; + view.matchesAlpha = false; + view.allowsHitTesting = false; + + return view; + } else { return nil; } - UIView *view = [[portalViewClass alloc] init]; - if (!view) { - return nil; - } - - view.forwardsClientHitTestingToSourceView = false; - view.matchesPosition = true; - view.matchesTransform = true; - view.matchesAlpha = false; - view.allowsHitTesting = false; - - return view; } diff --git a/submodules/UndoUI/Sources/UndoOverlayController.swift b/submodules/UndoUI/Sources/UndoOverlayController.swift index 4afcdbe5a9..eca1024b52 100644 --- a/submodules/UndoUI/Sources/UndoOverlayController.swift +++ b/submodules/UndoUI/Sources/UndoOverlayController.swift @@ -34,7 +34,7 @@ public enum UndoOverlayContent { case voiceChatRecording(text: String) case voiceChatFlag(text: String) case voiceChatCanSpeak(text: String) - case sticker(context: AccountContext, file: TelegramMediaFile, title: String?, text: String, undoText: String?) + case sticker(context: AccountContext, file: TelegramMediaFile, title: String?, text: String, undoText: String?, customAction: (() -> Void)?) case copy(text: String) case mediaSaved(text: String) case paymentSent(currencyValue: String, itemTitle: String) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index d0bb24e117..9915f8fae4 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -181,11 +181,18 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) - let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in return nil }), textAlignment: .natural) + let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor) + let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { contents in + return ("URL", contents) + }), textAlignment: .natural) self.textNode.attributedText = attributedText self.textNode.maximumNumberOfLines = 2 displayUndo = false self.originalRemainingSeconds = Double(max(5, min(8, text.count / 14))) + + if text.contains("](") { + isUserInteractionEnabled = true + } case let .actionSucceeded(title, text, cancel): self.avatarNode = nil self.iconNode = nil @@ -628,7 +635,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { displayUndo = false self.originalRemainingSeconds = 3 - case let .sticker(context, file, title, text, customUndoText): + case let .sticker(context, file, title, text, customUndoText, _): self.avatarNode = nil self.iconNode = nil self.iconCheckNode = nil @@ -880,17 +887,17 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { case .removedChat: self.panelWrapperNode.addSubnode(self.timerTextNode) case .archivedChat, .hidArchive, .revealedArchive, .autoDelete, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder, .messagesUnpinned, .setProximityAlert, .invitedToVoiceChat, .linkCopied, .banned, .importedMessage, .audioRate, .forward, .gigagroupConversion, .linkRevoked, .voiceChatRecording, .voiceChatFlag, .voiceChatCanSpeak, .copy, .mediaSaved, .paymentSent, .image, .inviteRequestSent, .notificationSoundAdded, .universal: - if self.textNode.tapAttributeAction != nil { + if self.textNode.tapAttributeAction != nil || displayUndo { self.isUserInteractionEnabled = true } else { self.isUserInteractionEnabled = false } - case let .sticker(_, _, _, _, undoText): - self.isUserInteractionEnabled = undoText != nil + case .sticker: + self.isUserInteractionEnabled = displayUndo case .dice: self.panelWrapperNode.clipsToBounds = true case .info: - if self.textNode.tapAttributeAction != nil { + if self.textNode.tapAttributeAction != nil || displayUndo { self.isUserInteractionEnabled = true } else { self.isUserInteractionEnabled = false @@ -963,7 +970,16 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } @objc private func undoButtonPressed() { - let _ = self.action(.undo) + switch self.content { + case let .sticker(_, _, _, _, _, customAction): + if let customAction = customAction { + customAction() + } else { + let _ = self.action(.undo) + } + default: + let _ = self.action(.undo) + } self.dismiss() } diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index 1e7392d6b5..6845840629 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -76,7 +76,7 @@ public enum ParsedInternalUrl { case peerName(String, ParsedInternalPeerUrlParameter?) case peerId(PeerId) case privateMessage(messageId: MessageId, threadId: Int32?, timecode: Double?) - case stickerPack(String) + case stickerPack(name: String, type: StickerPackUrlType) case invoice(String) case join(String) case localization(String) @@ -263,7 +263,9 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? { return .peerName(peerName, nil) } else if pathComponents.count == 2 || pathComponents.count == 3 { if pathComponents[0] == "addstickers" { - return .stickerPack(pathComponents[1]) + return .stickerPack(name: pathComponents[1], type: .stickers) + } else if pathComponents[0] == "addemoji" { + return .stickerPack(name: pathComponents[1], type: .emoji) } else if pathComponents[0] == "invoice" { return .invoice(pathComponents[1]) } else if pathComponents[0] == "joinchat" || pathComponents[0] == "joinchannel" { @@ -572,8 +574,8 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl) } } } - case let .stickerPack(name): - return .single(.stickerPack(name: name)) + case let .stickerPack(name, type): + return .single(.stickerPack(name: name, type: type)) case let .invoice(slug): return context.engine.payments.fetchBotPaymentInvoice(source: .slug(slug)) |> map(Optional.init) @@ -690,14 +692,14 @@ public func parseStickerPackUrl(_ url: String) -> String? { for scheme in schemes { let basePrefix = scheme + basePath + "/" if url.lowercased().hasPrefix(basePrefix) { - if let internalUrl = parseInternalUrl(query: String(url[basePrefix.endIndex...])), case let .stickerPack(name) = internalUrl { + if let internalUrl = parseInternalUrl(query: String(url[basePrefix.endIndex...])), case let .stickerPack(name, _) = internalUrl { return name } } } } if let parsedUrl = URL(string: url), parsedUrl.scheme == "tg", let host = parsedUrl.host, let query = parsedUrl.query { - if let internalUrl = parseInternalUrl(query: host + "?" + query), case let .stickerPack(name) = internalUrl { + if let internalUrl = parseInternalUrl(query: host + "?" + query), case let .stickerPack(name, _) = internalUrl { return name } } diff --git a/submodules/WallpaperBackgroundNode/Sources/MetalWallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/MetalWallpaperBackgroundNode.swift index e127f45cec..63d125ec96 100644 --- a/submodules/WallpaperBackgroundNode/Sources/MetalWallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/MetalWallpaperBackgroundNode.swift @@ -64,6 +64,7 @@ private func makePipelineState(device: MTLDevice, library: MTLLibrary, vertexPro return pipelineState } + @available(iOS 13.0, *) final class MetalWallpaperBackgroundNode: ASDisplayNode, WallpaperBackgroundNode { private let device: MTLDevice diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index 10149a2ec8..8b68f2a4ac 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -64,6 +64,212 @@ public protocol WallpaperBackgroundNode: ASDisplayNode { func makeDimmedNode() -> ASDisplayNode? } +private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOverlayLayer { + enum SoftlightMode { + case whileAnimating + case always + case never + } + + var patternContentImage: UIImage? { + didSet { + if self.patternContentImage !== oldValue { + self.updateComposedImage() + self.updateContents() + } + } + } + + var composedContentImage: UIImage? { + didSet { + if self.composedContentImage !== oldValue { + self.updateContents() + } + } + } + + var softlightMode: SoftlightMode = .whileAnimating { + didSet { + if self.softlightMode != oldValue { + self.updateFilters() + } + } + } + + var isAnimating: Bool = false { + didSet { + if self.isAnimating != oldValue { + self.updateFilters() + } + } + } + + private var isUsingSoftlight: Bool = false + + var suspendCompositionUpdates: Bool = false + private var needsCompositionUpdate: Bool = false + + private func updateFilters() { + let useSoftlight: Bool + let useFilter: Bool + switch self.softlightMode { + case .whileAnimating: + useSoftlight = self.isAnimating + useFilter = useSoftlight + case .always: + useSoftlight = true + useFilter = useSoftlight + case .never: + useSoftlight = true + useFilter = false + } + if self.isUsingSoftlight != useSoftlight { + self.isUsingSoftlight = useSoftlight + + if self.isUsingSoftlight && useFilter { + self.compositingFilter = "softLightBlendMode" + } else { + self.compositingFilter = nil + } + + self.updateContents() + self.updateOpacity() + } + } + + private var allowSettingContents: Bool = false + private var currentContents: UIImage? + + override var contents: Any? { + get { + return super.contents + } set(value) { + if self.allowSettingContents { + super.contents = value + } else { + assert(false) + } + } + } + + private var allowSettingOpacity: Bool = false + var compositionOpacity: Float = 1.0 { + didSet { + if self.compositionOpacity != oldValue { + self.updateOpacity() + self.updateComposedImage() + } + } + } + + override var opacity: Float { + get { + return super.opacity + } set(value) { + if self.allowSettingOpacity { + super.opacity = value + } else { + assert(false) + } + } + } + + private var compositionData: (size: CGSize, backgroundImage: UIImage, backgroundImageHash: String)? + + func updateCompositionData(size: CGSize, backgroundImage: UIImage, backgroundImageHash: String) { + if self.compositionData?.size == size && self.compositionData?.backgroundImage === backgroundImage { + return + } + self.compositionData = (size, backgroundImage, backgroundImageHash) + + self.updateComposedImage() + } + + func updateCompositionIfNeeded() { + if self.needsCompositionUpdate { + self.needsCompositionUpdate = false + self.updateComposedImage() + } + } + + private static var cachedComposedImage: (size: CGSize, patternContentImage: UIImage, backgroundImageHash: String, image: UIImage)? + + private func updateComposedImage() { + switch self.softlightMode { + case .always, .never: + return + default: + break + } + + if self.suspendCompositionUpdates { + self.needsCompositionUpdate = true + return + } + + guard let (size, backgroundImage, backgroundImageHash) = self.compositionData, let patternContentImage = self.patternContentImage else { + return + } + + if let cachedComposedImage = EffectImageLayer.cachedComposedImage, cachedComposedImage.size == size, cachedComposedImage.backgroundImageHash == backgroundImageHash, cachedComposedImage.patternContentImage === patternContentImage { + self.composedContentImage = cachedComposedImage.image + return + } + + #if DEBUG + let startTime = CFAbsoluteTimeGetCurrent() + #endif + + let composedContentImage = generateImage(size, contextGenerator: { size, context in + context.draw(backgroundImage.cgImage!, in: CGRect(origin: CGPoint(), size: size)) + context.setBlendMode(.softLight) + context.setAlpha(CGFloat(self.compositionOpacity)) + context.draw(patternContentImage.cgImage!, in: CGRect(origin: CGPoint(), size: size)) + }, opaque: true, scale: min(UIScreenScale, patternContentImage.scale)) + self.composedContentImage = composedContentImage + + #if DEBUG + print("Wallpaper composed image updated in \((CFAbsoluteTimeGetCurrent() - startTime) * 1000.0) ms") + #endif + + if self.softlightMode == .whileAnimating, let composedContentImage = composedContentImage { + EffectImageLayer.cachedComposedImage = (size, patternContentImage, backgroundImageHash, composedContentImage) + } + } + + private func updateContents() { + var contents: UIImage? + + if self.isUsingSoftlight { + contents = self.patternContentImage + } else { + contents = self.composedContentImage + } + + if self.currentContents !== contents { + self.currentContents = contents + + self.allowSettingContents = true + self.contents = contents?.cgImage + self.allowSettingContents = false + } + } + + private func updateOpacity() { + if self.isUsingSoftlight { + self.allowSettingOpacity = true + self.opacity = self.compositionOpacity + self.allowSettingOpacity = false + self.isOpaque = false + } else { + self.allowSettingOpacity = true + self.opacity = 1.0 + self.allowSettingOpacity = false + self.isOpaque = true + } + } +} + final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode { final class BubbleBackgroundNodeImpl: ASDisplayNode, WallpaperBubbleBackgroundNode { private let bubbleType: WallpaperBubbleType @@ -348,7 +554,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode private var gradientBackgroundNode: GradientBackgroundNode? private var outgoingBubbleGradientBackgroundNode: GradientBackgroundNode? - private let patternImageNode: ASImageNode + private let patternImageLayer: EffectImageLayer private var isGeneratingPatternImage: Bool = false private let bakedBackgroundView: UIImageView @@ -466,7 +672,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode self.contentNode = ASDisplayNode() self.contentNode.contentMode = self.imageContentMode - self.patternImageNode = ASImageNode() + self.patternImageLayer = EffectImageLayer() self.bakedBackgroundView = UIImageView() self.bakedBackgroundView.isHidden = true @@ -476,49 +682,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode self.clipsToBounds = true self.contentNode.frame = self.bounds self.addSubnode(self.contentNode) - self.addSubnode(self.patternImageNode) - - /*let animationList: [(String, CGPoint)] = [ - ("ptrnCAT_1162_1918", CGPoint(x: 1162 - 256, y: 1918 - 256)), - ("ptrnDOG_0440_2284", CGPoint(x: 440 - 256, y: 2284 - 256)), - ("ptrnGLOB_0438_1553", CGPoint(x: 438 - 256, y: 1553 - 256)), - ("ptrnSLON_0906_1033", CGPoint(x: 906 - 256, y: 1033 - 256)) - ] - for (animation, relativePosition) in animationList { - let animationNode = DefaultAnimatedStickerNodeImpl() - animationNode.automaticallyLoadFirstFrame = true - animationNode.autoplay = true - //self.inlineAnimationNodes.append((animationNode, relativePosition)) - self.patternImageNode.addSubnode(animationNode) - animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animation), width: 256, height: 256, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - } - - self.layer.addSublayer(self.hierarchyTrackingLayer) - self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in - guard let strongSelf = self else { - return - } - for (animationNode, _) in strongSelf.inlineAnimationNodes { - animationNode.visibility = true - } - strongSelf.activateInlineAnimationTimer = SwiftSignalKit.Timer(timeout: 5.0, repeat: true, completion: { - guard let strongSelf = self else { - return - } - - strongSelf.inlineAnimationNodes[Int.random(in: 0 ..< strongSelf.inlineAnimationNodes.count)].0.play() - }, queue: .mainQueue()) - strongSelf.activateInlineAnimationTimer?.start() - } - self.hierarchyTrackingLayer.didExitHierarchy = { [weak self] in - guard let strongSelf = self else { - return - } - for (animationNode, _) in strongSelf.inlineAnimationNodes { - animationNode.visibility = false - } - strongSelf.activateInlineAnimationTimer?.invalidate() - }*/ + self.layer.addSublayer(self.patternImageLayer) } deinit { @@ -556,7 +720,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode let gradientBackgroundNode = createGradientBackgroundNode(colors: mappedColors, useSharedAnimationPhase: self.useSharedAnimationPhase) self.gradientBackgroundNode = gradientBackgroundNode self.insertSubnode(gradientBackgroundNode, aboveSubnode: self.contentNode) - gradientBackgroundNode.addSubnode(self.patternImageNode) + gradientBackgroundNode.setPatternOverlay(layer: self.patternImageLayer) } self.gradientBackgroundNode?.updateColors(colors: mappedColors) @@ -569,7 +733,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode if let gradientBackgroundNode = self.gradientBackgroundNode { self.gradientBackgroundNode = nil gradientBackgroundNode.removeFromSupernode() - self.insertSubnode(self.patternImageNode, aboveSubnode: self.contentNode) + gradientBackgroundNode.setPatternOverlay(layer: nil) + self.layer.insertSublayer(self.patternImageLayer, above: self.contentNode.layer) } self.motionEnabled = wallpaper.settings?.motion ?? false @@ -654,40 +819,44 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode let intensity = CGFloat(file.settings.intensity ?? 50) / 100.0 if intensity < 0 { - self.patternImageNode.alpha = 1.0 - self.patternImageNode.layer.compositingFilter = nil + self.patternImageLayer.compositionOpacity = 1.0 + self.patternImageLayer.softlightMode = .never } else { - self.patternImageNode.alpha = intensity + self.patternImageLayer.compositionOpacity = Float(intensity) if patternIsBlack { - self.patternImageNode.layer.compositingFilter = nil + self.patternImageLayer.softlightMode = .never } else { - self.patternImageNode.layer.compositingFilter = "softLightBlendMode" + if self.useSharedAnimationPhase { + self.patternImageLayer.softlightMode = .whileAnimating + } else { + self.patternImageLayer.softlightMode = .always + } } } - self.patternImageNode.isHidden = false + self.patternImageLayer.isHidden = false let invertPattern = intensity < 0 if invertPattern { self.backgroundColor = .black let contentAlpha = abs(intensity) self.gradientBackgroundNode?.contentView.alpha = contentAlpha self.contentNode.alpha = contentAlpha - if self.patternImageNode.image != nil { - self.patternImageNode.backgroundColor = nil + if self.patternImageLayer.contents != nil { + self.patternImageLayer.backgroundColor = nil } else { - self.patternImageNode.backgroundColor = .black + self.patternImageLayer.backgroundColor = nil } } else { self.backgroundColor = nil self.gradientBackgroundNode?.contentView.alpha = 1.0 self.contentNode.alpha = 1.0 - self.patternImageNode.backgroundColor = nil + self.patternImageLayer.backgroundColor = nil } default: self.patternImageDisposable.set(nil) self.validPatternImage = nil - self.patternImageNode.isHidden = true - self.patternImageNode.backgroundColor = nil + self.patternImageLayer.isHidden = true + self.patternImageLayer.backgroundColor = nil self.backgroundColor = nil self.gradientBackgroundNode?.contentView.alpha = 1.0 self.contentNode.alpha = 1.0 @@ -784,10 +953,10 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode if invertPattern { patternColor = .clear patternBackgroundColor = .clear - if self.patternImageNode.image == nil { - self.patternImageNode.backgroundColor = .black + if self.patternImageLayer.contents == nil { + self.patternImageLayer.backgroundColor = UIColor.black.cgColor } else { - self.patternImageNode.backgroundColor = nil + self.patternImageLayer.backgroundColor = nil } } else { if patternIsLight { @@ -796,7 +965,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode patternColor = .white } patternBackgroundColor = .clear - self.patternImageNode.backgroundColor = nil + self.patternImageLayer.backgroundColor = nil } let updatedGeneratedImage = ValidPatternGeneratedImage(wallpaper: validPatternImage.wallpaper, size: size, patternColor: patternColor.rgb, backgroundColor: patternBackgroundColor.rgb, invertPattern: invertPattern) @@ -805,15 +974,21 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode self.validPatternGeneratedImage = updatedGeneratedImage if let cachedValidPatternImage = WallpaperBackgroundNodeImpl.cachedValidPatternImage, cachedValidPatternImage.generated == updatedGeneratedImage { - self.patternImageNode.image = cachedValidPatternImage.image + self.patternImageLayer.suspendCompositionUpdates = true self.updatePatternPresentation() + self.patternImageLayer.patternContentImage = cachedValidPatternImage.image + self.patternImageLayer.suspendCompositionUpdates = false + self.patternImageLayer.updateCompositionIfNeeded() } else { let patternArguments = TransformImageArguments(corners: ImageCorners(), imageSize: size, boundingSize: size, intrinsicInsets: UIEdgeInsets(), custom: PatternWallpaperArguments(colors: [patternBackgroundColor], rotation: nil, customPatternColor: patternColor, preview: false), scale: min(2.0, UIScreenScale)) - if self.useSharedAnimationPhase || self.patternImageNode.image == nil { + if self.useSharedAnimationPhase || self.patternImageLayer.contents == nil { if let drawingContext = validPatternImage.generate(patternArguments) { if let image = drawingContext.generateImage() { - self.patternImageNode.image = image + self.patternImageLayer.suspendCompositionUpdates = true self.updatePatternPresentation() + self.patternImageLayer.patternContentImage = image + self.patternImageLayer.suspendCompositionUpdates = false + self.patternImageLayer.updateCompositionIfNeeded() if self.useSharedAnimationPhase { WallpaperBackgroundNodeImpl.cachedValidPatternImage = CachedValidPatternImage(generate: validPatternImage.generate, generated: updatedGeneratedImage, image: image) @@ -833,7 +1008,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode return } strongSelf.isGeneratingPatternImage = false - strongSelf.patternImageNode.image = image + strongSelf.patternImageLayer.patternContentImage = image strongSelf.updatePatternPresentation() if let image = image, strongSelf.useSharedAnimationPhase { @@ -856,7 +1031,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode } } - transition.updateFrame(node: self.patternImageNode, frame: CGRect(origin: CGPoint(), size: size)) + transition.updateFrame(layer: self.patternImageLayer, frame: CGRect(origin: CGPoint(), size: size)) } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { diff --git a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift index 323fb6e64e..1f348c5f9f 100644 --- a/submodules/WatchBridge/Sources/WatchRequestHandlers.swift +++ b/submodules/WatchBridge/Sources/WatchRequestHandlers.swift @@ -199,17 +199,17 @@ final class WatchSendMessageHandler: WatchRequestHandler { if args.replyToMid != 0, let peerId = peerId { replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.replyToMid) } - messageSignal = .single((.message(text: args.text, attributes: [], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil), peerId)) + messageSignal = .single((.message(text: args.text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil), peerId)) } else if let args = subscription as? TGBridgeSendLocationMessageSubscription, let location = args.location { let peerId = makePeerIdFromBridgeIdentifier(args.peerId) let map = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: makeVenue(from: location.venue), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil) - messageSignal = .single((.message(text: "", attributes: [], mediaReference: .standalone(media: map), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId)) + messageSignal = .single((.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: map), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId)) } else if let args = subscription as? TGBridgeSendStickerMessageSubscription { let peerId = makePeerIdFromBridgeIdentifier(args.peerId) messageSignal = mediaForSticker(documentId: args.document.documentId, account: context.account) |> map({ media -> (EnqueueMessage?, PeerId?) in if let media = media { - return (.message(text: "", attributes: [], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId) + return (.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil), peerId) } else { return (nil, nil) } @@ -720,7 +720,7 @@ final class WatchAudioHandler: WatchRequestHandler { replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToMid) } - let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]).start() + let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil)]).start() } }) } else { diff --git a/submodules/WebUI/BUILD b/submodules/WebUI/BUILD index 09c1980683..b8b9bbadc3 100644 --- a/submodules/WebUI/BUILD +++ b/submodules/WebUI/BUILD @@ -27,6 +27,7 @@ swift_library( "//submodules/MoreButtonNode:MoreButtonNode", "//submodules/BotPaymentsUI:BotPaymentsUI", "//submodules/PromptUI:PromptUI", + "//submodules/PhoneNumberFormat:PhoneNumberFormat", ], visibility = [ "//visibility:public", diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 216afd8217..e939b3a9d5 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -20,6 +20,7 @@ import UrlHandling import MoreButtonNode import BotPaymentsUI import PromptUI +import PhoneNumberFormat private let durgerKingBotIds: [Int64] = [5104055776, 2200339955] @@ -468,6 +469,11 @@ public final class WebAppController: ViewController, AttachmentContainable { let alertController = textAlertController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, title: nil, text: message, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { completionHandler() })]) + alertController.dismissed = { byOutsideTap in + if byOutsideTap { + completionHandler() + } + } self.controller?.present(alertController, in: .window(.root)) } @@ -477,6 +483,11 @@ public final class WebAppController: ViewController, AttachmentContainable { }), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { completionHandler(true) })]) + alertController.dismissed = { byOutsideTap in + if byOutsideTap { + completionHandler(false) + } + } self.controller?.present(alertController, in: .window(.root)) } @@ -488,6 +499,11 @@ public final class WebAppController: ViewController, AttachmentContainable { completionHandler(nil) } }) + promptController.dismissed = { byOutsideTap in + if byOutsideTap { + completionHandler(nil) + } + } self.controller?.present(promptController, in: .window(.root)) } @@ -723,11 +739,108 @@ public final class WebAppController: ViewController, AttachmentContainable { self.headerColorKey = colorKey self.updateHeaderBackgroundColor(transition: .animated(duration: 0.2, curve: .linear)) } + case "web_app_open_popup": + if let json = json, let message = json["message"] as? String, let buttons = json["buttons"] as? [Any] { + let presentationData = self.presentationData + + let title = json["title"] as? String + var alertButtons: [TextAlertAction] = [] + + for buttonJson in buttons { + if let button = buttonJson as? [String: Any], let id = button["id"] as? String, let type = button["type"] as? String { + let buttonAction = { + self.sendAlertButtonEvent(id: id) + } + let text = button["text"] as? String + switch type { + case "default": + if let text = text { + alertButtons.append(TextAlertAction(type: .genericAction, title: text, action: { + buttonAction() + })) + } + case "destructive": + if let text = text { + alertButtons.append(TextAlertAction(type: .destructiveAction, title: text, action: { + buttonAction() + })) + } + case "ok": + alertButtons.append(TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { + buttonAction() + })) + case "cancel": + alertButtons.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { + buttonAction() + })) + case "close": + alertButtons.append(TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Close, action: { + buttonAction() + })) + default: + break + } + } + } + + var actionLayout: TextAlertContentActionLayout = .horizontal + if alertButtons.count > 2 { + actionLayout = .vertical + } + let alertController = textAlertController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, title: title, text: message, actions: alertButtons, actionLayout: actionLayout) + alertController.dismissed = { byOutsideTap in + if byOutsideTap { + self.sendAlertButtonEvent(id: nil) + } + } + self.controller?.present(alertController, in: .window(.root)) + } + case "web_app_setup_closing_behavior": + if let json = json, let needConfirmation = json["need_confirmation"] as? Bool { + self.needDismissConfirmation = needConfirmation + } + case "web_app_request_phone": + break +// let _ = (self.context.account.postbox.loadedPeerWithId(self.context.account.peerId) +// |> deliverOnMainQueue).start(next: { [weak self] accountPeer in +// guard let strongSelf = self else { +// return +// } +// guard let user = accountPeer as? TelegramUser, let phoneNumber = user.phone else { +// return +// } +// +// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) +// var items: [ActionSheetItem] = [] +// items.append(ActionSheetTextItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumberConfirmation(formatPhoneNumber(phoneNumber), strongSelf.controller?.botName ?? "").string, parseMarkdown: true)) +// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.WebApp_ShareMyPhoneNumber, action: { [weak actionSheet] in +// actionSheet?.dismissAnimated() +// guard let strongSelf = self else { +// return +// } +// +// strongSelf.sendPhoneRequestedEvent(phone: phoneNumber) +// })) +// +// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ +// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in +// actionSheet?.dismissAnimated() +// guard let strongSelf = self else { +// return +// } +// +// strongSelf.sendPhoneRequestedEvent(phone: nil) +// }) +// ])]) +// strongSelf.controller?.present(actionSheet, in: .window(.root)) +// }) default: break } } + fileprivate var needDismissConfirmation = false + private var headerColorKey: String? private func updateHeaderBackgroundColor(transition: ContainedViewLayoutTransition) { let color: UIColor? @@ -834,6 +947,22 @@ public final class WebAppController: ViewController, AttachmentContainable { fileprivate func sendSettingsButtonEvent() { self.webView?.sendEvent(name: "settings_button_pressed", data: nil) } + + fileprivate func sendAlertButtonEvent(id: String?) { + var paramsString: String? + if let id = id { + paramsString = "{button_id: \"\(id)\"}" + } + self.webView?.sendEvent(name: "popup_closed", data: paramsString) + } + + fileprivate func sendPhoneRequestedEvent(phone: String?) { + var paramsString: String? + if let phone = phone { + paramsString = "{phone_number: \"\(phone)\"}" + } + self.webView?.sendEvent(name: "phone_requested", data: paramsString) + } } fileprivate var controllerNode: Node { @@ -945,7 +1074,9 @@ public final class WebAppController: ViewController, AttachmentContainable { if case .back = self.cancelButtonNode.state { self.controllerNode.sendBackButtonEvent() } else { - self.dismiss() + self.requestDismiss { + self.dismiss() + } } } @@ -961,6 +1092,7 @@ public final class WebAppController: ViewController, AttachmentContainable { let botId = self.botId let items = context.engine.messages.attachMenuBots() + |> take(1) |> map { [weak self] attachMenuBots -> ContextController.Items in var items: [ContextMenuItem] = [] @@ -969,8 +1101,8 @@ public final class WebAppController: ViewController, AttachmentContainable { if self?.url == nil, let attachMenuBot = attachMenuBot, attachMenuBot.hasSettings { items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_Settings, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Settings"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, f in - f(.default) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) if let strongSelf = self { strongSelf.controllerNode.sendSettingsButtonEvent() @@ -981,8 +1113,8 @@ public final class WebAppController: ViewController, AttachmentContainable { if peerId != botId { items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_OpenBot, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Bots"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, f in - f(.default) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) if let strongSelf = self, let navigationController = strongSelf.getNavigationController() { strongSelf.dismiss() @@ -993,8 +1125,8 @@ public final class WebAppController: ViewController, AttachmentContainable { items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_ReloadPage, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reload"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, f in - f(.default) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) self?.controllerNode.webView?.reload() }))) @@ -1002,8 +1134,8 @@ public final class WebAppController: ViewController, AttachmentContainable { if let _ = attachMenuBot, self?.url == nil { items.append(.action(ContextMenuActionItem(text: presentationData.strings.WebApp_RemoveBot, textColor: .destructive, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) - }, action: { [weak self] _, f in - f(.default) + }, action: { [weak self] c, _ in + c.dismiss(completion: nil) if let strongSelf = self { let presentationData = context.sharedContext.currentPresentationData.with { $0 } @@ -1055,6 +1187,38 @@ public final class WebAppController: ViewController, AttachmentContainable { public func prepareForReuse() { self.updateTabBarAlpha(1.0, .immediate) } + + public func requestDismiss(completion: @escaping () -> Void) { + if self.controllerNode.needDismissConfirmation { + let actionSheet = ActionSheetController(presentationData: self.presentationData) + actionSheet.setItemGroups([ + ActionSheetItemGroup(items: [ + ActionSheetTextItem(title: self.presentationData.strings.WebApp_CloseConfirmation), + ActionSheetButtonItem(title: self.presentationData.strings.WebApp_CloseAnyway, color: .destructive, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + + completion() + }) + ]), + ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ]) + ]) + self.present(actionSheet, in: .window(.root)) + } else { + completion() + } + } + + public func shouldDismissImmediately() -> Bool { + if self.controllerNode.needDismissConfirmation { + return false + } else { + return true + } + } } final class WebAppPickerContext: AttachmentMediaPickerContext { @@ -1110,7 +1274,9 @@ private final class WebAppContextReferenceContentSource: ContextReferenceContent } public func standaloneWebAppController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, params: WebAppParameters, openUrl: @escaping (String) -> Void, getInputContainerNode: @escaping () -> (CGFloat, ASDisplayNode, () -> AttachmentController.InputPanelTransition?)? = { return nil }, completion: @escaping () -> Void = {}, willDismiss: @escaping () -> Void = {}, didDismiss: @escaping () -> Void = {}, getNavigationController: @escaping () -> NavigationController? = { return nil }) -> ViewController { - let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.fromMenu) + let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.fromMenu, makeEntityInputView: { + return nil + }) controller.getInputContainerNode = getInputContainerNode controller.requestController = { _, present in let webAppController = WebAppController(context: context, updatedPresentationData: updatedPresentationData, params: params, replyToMessageId: nil) diff --git a/submodules/YuvConversion/PublicHeaders/YuvConversion/YUV.h b/submodules/YuvConversion/PublicHeaders/YuvConversion/YUV.h index d47d16e3c5..60e3e5a2fd 100644 --- a/submodules/YuvConversion/PublicHeaders/YuvConversion/YUV.h +++ b/submodules/YuvConversion/PublicHeaders/YuvConversion/YUV.h @@ -4,4 +4,4 @@ void encodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, void resizeAndEncodeRGBAToYUVA(uint8_t *yuva, uint8_t const *argb, int width, int height, int bytesPerRow, int originalWidth, int originalHeight, int originalBytesPerRow, bool unpremultiply); void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, int bytesPerRow); -void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow); +void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow, bool unpremultiply); diff --git a/submodules/YuvConversion/Sources/YUV.m b/submodules/YuvConversion/Sources/YUV.m index e99f101d1c..e8d4609878 100644 --- a/submodules/YuvConversion/Sources/YUV.m +++ b/submodules/YuvConversion/Sources/YUV.m @@ -173,7 +173,7 @@ void decodeYUVAToRGBA(uint8_t const *yuva, uint8_t *argb, int width, int height, } } -void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow) { +void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint8_t const *srcCbData, int srcCbBytesPerRow, uint8_t const *srcCrData, int srcCrBytesPerRow, bool hasAlpha, uint8_t const *alphaData, uint8_t *argb, int width, int height, int bytesPerRow, bool unpremultiply) { static vImage_YpCbCrToARGB info; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -220,7 +220,11 @@ void decodeYUVAPlanesToRGBA(uint8_t const *srcYpData, int srcYpBytesPerRow, uint } uint8_t permuteMap[4] = {3, 2, 1, 0}; - error = vImageUnpremultiplyData_ARGB8888(&dest, &dest, kvImageDoNotTile); + if (unpremultiply) { + error = vImageUnpremultiplyData_ARGB8888(&dest, &dest, kvImageDoNotTile); + } else { + error = vImagePremultiplyData_ARGB8888(&dest, &dest, kvImageDoNotTile); + } error = vImagePermuteChannels_ARGB8888(&dest, &dest, permuteMap, kvImageDoNotTile); if (error != kvImageNoError) { diff --git a/submodules/lottie-ios/Sources/Private/CoreAnimation/CoreAnimationLayer.swift b/submodules/lottie-ios/Sources/Private/CoreAnimation/CoreAnimationLayer.swift index 05f140e59f..2507d457d8 100644 --- a/submodules/lottie-ios/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +++ b/submodules/lottie-ios/Sources/Private/CoreAnimation/CoreAnimationLayer.swift @@ -393,6 +393,10 @@ extension CoreAnimationLayer: RootAnimationLayer { func logHierarchyKeypaths() { // Unimplemented / unused } + + func allKeypaths(predicate: (AnimationKeypath) -> Bool) -> [String] { + return [] + } func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { valueProviderStore.setValueProvider(valueProvider, keypath: keypath) diff --git a/submodules/lottie-ios/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift b/submodules/lottie-ios/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift index d93a7f603c..ffc0d1eab4 100644 --- a/submodules/lottie-ios/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +++ b/submodules/lottie-ios/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift @@ -203,6 +203,14 @@ final class MainThreadAnimationLayer: CALayer, RootAnimationLayer { print("Lottie: Logging Animation Keypaths") animationLayers.forEach({ $0.logKeypaths(for: nil) }) } + + func allKeypaths(predicate: (AnimationKeypath) -> Bool) -> [String] { + var result: [String] = [] + for animationLayer in animationLayers { + result.append(contentsOf: animationLayer.allKeypaths(for: nil, predicate: predicate)) + } + return result + } func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) { for layer in animationLayers { diff --git a/submodules/lottie-ios/Sources/Private/RootAnimationLayer.swift b/submodules/lottie-ios/Sources/Private/RootAnimationLayer.swift index d3ab01085e..ea586f66c4 100644 --- a/submodules/lottie-ios/Sources/Private/RootAnimationLayer.swift +++ b/submodules/lottie-ios/Sources/Private/RootAnimationLayer.swift @@ -32,6 +32,7 @@ protocol RootAnimationLayer: CALayer { func reloadImages() func forceDisplayUpdate() func logHierarchyKeypaths() + func allKeypaths(predicate: (AnimationKeypath) -> Bool) -> [String] func setValueProvider(_ valueProvider: AnyValueProvider, keypath: AnimationKeypath) func getValue(for keypath: AnimationKeypath, atFrame: AnimationFrameTime?) -> Any? diff --git a/submodules/lottie-ios/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift b/submodules/lottie-ios/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift index 08b6e3aa6d..7e31179780 100644 --- a/submodules/lottie-ios/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +++ b/submodules/lottie-ios/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift @@ -130,6 +130,29 @@ extension KeypathSearchable { child.logKeypaths(for: newKeypath) } } + + func allKeypaths(for keyPath: AnimationKeypath?, predicate: (AnimationKeypath) -> Bool) -> [String] { + var result: [String] = [] + let newKeypath: AnimationKeypath + if let previousKeypath = keyPath { + newKeypath = previousKeypath.appendingKey(keypathName) + } else { + newKeypath = AnimationKeypath(keys: [keypathName]) + } + if predicate(newKeypath) { + result.append(newKeypath.fullPath) + } + for key in keypathProperties.keys { + let subKey = newKeypath.appendingKey(key) + if predicate(subKey) { + result.append(subKey.fullPath) + } + } + for child in childKeypaths { + result.append(contentsOf: child.allKeypaths(for: newKeypath, predicate: predicate)) + } + return result + } } extension AnimationKeypath { diff --git a/submodules/lottie-ios/Sources/Public/Animation/AnimationView.swift b/submodules/lottie-ios/Sources/Public/Animation/AnimationView.swift index 55d0c04b68..f2b1b96186 100644 --- a/submodules/lottie-ios/Sources/Public/Animation/AnimationView.swift +++ b/submodules/lottie-ios/Sources/Public/Animation/AnimationView.swift @@ -621,6 +621,10 @@ final public class AnimationView: AnimationViewBase { public func logHierarchyKeypaths() { animationLayer?.logHierarchyKeypaths() } + + public func allKeypaths(predicate: (AnimationKeypath) -> Bool) -> [String] { + return animationLayer?.allKeypaths(predicate: predicate) ?? [] + } /// Searches for the nearest child layer to the first Keypath and adds the subview /// to that layer. The subview will move and animate with the child layer. diff --git a/submodules/lottie-ios/Sources/Public/DynamicProperties/AnimationKeypath.swift b/submodules/lottie-ios/Sources/Public/DynamicProperties/AnimationKeypath.swift index f1b6748331..860dfc7da9 100644 --- a/submodules/lottie-ios/Sources/Public/DynamicProperties/AnimationKeypath.swift +++ b/submodules/lottie-ios/Sources/Public/DynamicProperties/AnimationKeypath.swift @@ -44,6 +44,6 @@ public struct AnimationKeypath: Hashable, ExpressibleByStringLiteral { self.keys = keys } - var keys: [String] + public var keys: [String] } diff --git a/versions.json b/versions.json index c202f0582b..6680658187 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "8.8.3", + "app": "8.9", "bazel": "5.1.0", "xcode": "13.4.1" }